How to determine (at runtime) if a variable is annotated as deprecated? - java

This code can check whether a class is deprecated or not
#Deprecated
public classRetentionPolicyExample{
public static void main(String[] args){
boolean isDeprecated=false;
if(RetentionPolicyExample.class.getAnnotations().length>0){
isDeprecated= RetentionPolicyExample.class
.getAnnotations()[0].toString()
.contains("Deprecated");
}
System.out.println("is deprecated:"+ isDeprecated);
}
}
But, how can be checked if any variable is annotated as deprecated?
#Deprecated
Stringvariable;

import java.util.stream.Stream;
Field[] fields = RetentionPolicyExample.class // Get the class
.getDeclaredFields(); // Get its fields
boolean isAnyDeprecated = Stream.of(fields) // Iterate over fields
// If it is deprecated, this gets the annotation.
// Else, null
.map(field -> field.getAnnotation(Deprecated.class))
.anyMatch(x -> x != null); // Is there a deprecated annotation somewhere?

You are checking the Class annotations. The reflection API's also give you access to Field and Method annotations.
See
Class.getFields() and Class.getDeclaredFields()
Class.getMethods() and Class.getDeclaredMethods()
Class.getSuperClass()
A couple of problems with your implementation
You are only checking getAnnotations[0] when there might be more than one annotation
You are testing toString().contains("Deprecated") when you should check .equals(Deprecated.class)
You could use .getAnnotation(Deprecated.class)

Related

Create Custom Field Annotation to check Null value in java

I need to create Custom annotation in java to check null value *i.e
#NonNull
public void test(String [] input , String str){
}
How to add the annoation to input and str fields
When creating your Annotation class, you have to add the #Target annotation to mark where this Annotation is valid. For parameters this would be ElementType.PARAMETER.
This minimal example will compile. (The Interface is a private nested class here, but you will want to define it in its own .java file)
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
private static #interface NonNull {
}
public void test(#NonNull String[] input, #NonNull String str) {
}
Note that this does not provide any null-checking, but tells the caller that this parameters may not be null in the function.
I'm pretty sure you can implement some kind of null-checking in the annotation class, but I'm not sure, so that has to be answered by someone else or you can probably look at some existing implementations of #NonNull interfaces.

How does Java implements the methods declared in the Annotations (Metadata)?

An image taken from a book which I am going through,
The caption says it all. Please suggest or give me something as to what happens behind the scenes.
For example, how does #NotNull in Hibernate Bean Validation API works?
I know that through Reflection API, we can do something like this,
class Meta {
// Annotate a method.
#MyAnno(str = "Annotation Example", val = 100)
public static void myMeth() {
Meta ob = new Meta();
// Obtain the annotation for this method
// and display the values of the members.
try {
// First, get a Class object that represents
// this class.
Class c = ob.getClass();
// Now, get a Method object that represents
// this method.
Method m = c.getMethod("myMeth");
// Next, get the annotation for this class.
MyAnno anno = m.getAnnotation(MyAnno.class);
// Finally, display the values.
System.out.println(anno.str() + " " + anno.val());
} catch (NoSuchMethodException exc) {
System.out.println("Method Not Found.");
}
}
public static void main(String args[]) {
myMeth();
}
}
Annotations don't have any implemented code and actually don't do anything themself.
To make them "work", there should be some kind of annotation processor (initializer, loader or any class that works with annotated objects). This annotation processor checks annotation objects annotations and changes the way it is handled.
For example Spring annotation processor, when initializing an object, looks for #Autowired fields, to fill autowired fields.
Same goes for Hibernates #NotNull. it doesn't do anything actually. However, Hibernate, when persisting your object, checks if there should be something there.

Java annotation to set field to a static instance?

I've been playing with annotations, and I'm wondering how to go about doing this. What I'd like to do is to be able to have a field declared in a class and annotated such that the field will be initialized with a static instance of the class.
Given an annotation like this:
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME) //or would this be RetentionPolicy.CLASS?
public #interface SetThisField {
}
Something like this:
public class Foo {
#SetThisField
private Bar bar;
}
I've played around with using a parser and setting this at runtime, which works but isn't as elegant as I'd like.
I can't find any really good examples of RetentionPolicy.CLASS but the documentation seems to indicate that I could somehow make the declaration of "bar" get compiled into this:
private Bar bar = Bar.getInstance();
It wouldn't look that way in the source code of course, but it would in the byte code and it would behave like that at runtime.
So am I off base here? Is this possible? Or is the parser the way to go with it?
UPDATE: This is the guts of the parser I'm using
public static void parse(Object instance) throws Exception {
Field[] fields = instance.getClass().getDeclaredFields();
for (Field field : fields) {
//"Property" annotated fields get set to an application.properties value
//using the value of the annotation as the key into the properties
if (field.isAnnotationPresent(Property.class)) {
Property property = field.getAnnotation(Property.class);
String value = property.value();
if (!"".equals(value)) {
setFieldValue(instance, field, properties.getProperty(value));
}
}
//"Resource" annotated fields get static instances of the class allocated
//based upon the type of the field.
if (field.isAnnotationPresent(Resource.class)) {
String name = field.getType().getName();
setFieldValue(instance, field, MyApplication.getResources().get(name));
}
}
}
private static void setFieldValue(Object instance, Field field, Object value) throws IllegalAccessException {
boolean accessibleState = field.isAccessible();
field.setAccessible(true);
field.set(instance, value);
field.setAccessible(accessibleState);
}
I would suggest doing the replacement at run time. This is much simpler to implement and test. Changing the byte code at build time is relatively error prone and tricky to get right. For example you would need to understand how byte code is structured and in this case how to add the code to all the constructors in the right place in the code.
If you make the retention RUNTIME, you can have a library which examines the annotation and sets the value after the object is created.

Finding annotations on an interface

I have an inteface Foo with an implementation Bar. The interface Foo has a method "doMe()" with a method annotation #Secured. This is the only method that is secured.
Now I wrote the following code to go through classes and look for methods with #Secured on them. (This method is not finished yet, I'm trying to get the first unit tests passed.)
/**
* Determine if a method is secured
* #param method the method being checked
* #return true if the method is secured, false otherwise
*/
protected static boolean isSecured(Method method) {
boolean secured = false;
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation:annotations){
if(Secured.class.equals(annotation.getClass())){
secured = true;
break;
}
}
if(secured){
return true;
}
return secured;
}
Methods besides doMe() return 0 members on getAnnotations() for both Foo and Bar. The problem is that doMe() also returns 0 members for both Foo and Bar.
I'm looking for someone that knows more about reflection than me, since that shouldn't be hard to find. :)
Thanks.
Have you ensured that the annotation is visible at runtime? You may need to annotate your annotation with #Retention(RetentionPolicy.RUNTIME). The default, CLASS, won't return the annotation in reflective methods.
See also: RetentionPolicy docs
Try using getAnnotation instead of getAnnotations, because getAnotations internally uses getDeclaredAnnotations.
More details at Method (Java Platform SE 6)
protected static boolean isSecured(Method method) {
Secured secured = method.getAnnotation(Secured.class);
return secured == null ? false : true;
}

How do app servers inject into private fields?

I saw this question
Inject into private, package or public field or provide a setter?
about how to manually inject into annotated private fields (The way is adding setters
or through a constructor)
But, the point is how do an application server (like glassfish, axis2, jboss, ...)
is able to inject into a final private field (without adding setters or constructors
to the user class)?
Quoting the cited question:
public SomeClass {
#Inject
private SomeResource resource;
}
Do they use a customized JVM (not the standard one) that allows to access private fields?
Thanks
It's a simple reflection "trick". It relies on the Field.setAccessible() method to force the member to be accessible programmatically:
Set the accessible flag for this
object to the indicated boolean value.
A value of true indicates that the
reflected object should suppress Java
language access checking when it is
used. A value of false indicates that
the reflected object should enforce
Java language access checks.
The Reflection API is used to get a handle on the field, setAccessible() is called, and then it can be set by the injection framework.
See an example here.
No magic, no custom VM.
With the help of skaffman I coded this simple example on how to inject without setters.
Perhaps it helps (It did to me)
//......................................................
import java.lang.annotation.*;
import java.lang.reflect.*;
//......................................................
#Target(value = {ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#interface Inject {
}
//......................................................
class MyClass {
#Inject
private int theValue = 0;
public int getTheValue() {
return theValue;
}
} // class
//......................................................
public class Example {
//......................................................
private static void doTheInjection(MyClass u, int value) throws IllegalAccessException {
Field[] camps = u.getClass().getDeclaredFields();
System.out.println("------- fields : --------");
for (Field f : camps) {
System.out.println(" -> " + f.toString());
Annotation an = f.getAnnotation(Inject.class);
if (an != null) {
System.out.println(" found annotation: " + an.toString());
System.out.println(" injecting !");
f.setAccessible(true);
f.set(u, value);
f.setAccessible(false);
}
}
} // ()
//......................................................
public static void main(String[] args) throws Exception {
MyClass u = new MyClass();
doTheInjection(u, 23);
System.out.println(u.getTheValue());
} // main ()
} // class
Run output:
------- fields : --------
-> private int MyClass.theValue
found annotation: #Inject()
injecting !
23
It's also worth noting, that some frameworks utilize bytecode engineering via a custom classloader to achieve the same result without the cost of Reflection (reflection can be pretty expensive at times)

Categories

Resources