I am in a situation where I am getting all the annotations of a class using
final Annotation[] annotations = declaringClass.getAnnotations();
Now I know that one of the annotations is of type MyAnnotation which has the following format
public #interface MyAnnotation {
boolean state() default true;
I would like to be able to get the value set for the parameter state, how do I do this? Annotation seems to be a proxy and not the actual object.
If you're just looking for that particular annotation, you can get it directly like this:
MyAnnotation a = declaringClass.getAnnotation(MyAnnotation.class);
boolean state = a.state();
If you specifically want it from your array, just cast it:
MyAnnotation a = (MyAnnotation)annotations[i];
boolean state = a.state();
Related
Is it possible to document that return value is not null with Java Optional?
Most tools and frameworks care only about arguments but I'd like to express in type that return value is not null (instead of doing that in JavaDoc).
UPDATE Looks like you can agree with team to use Optional as return value if you want to express possible null and direct object when it is definitely not null:
public Optional<Job> getJob() { ... }
public Job extractJob(NonNullJobHolder<Job> holder) { ... }
I don't know why you're under the impression that most of them apply only to parameters.
org.eclipse.jdt.annotation.NonNull
#Documented
#Retention(value=CLASS)
#Target(value={FIELD,METHOD,PARAMETER,LOCAL_VARIABLE})
public #interface NonNull
org.jetbrains.annotations.NotNull
The #NotNull annotation is, actually, an explicit contract declaring
that:
A method should not return null
Variables (fields, local variables, and parameters) cannot hold a null value
Usage:
javax.validation.constraints.NotNull
#Target(value={METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})
#Retention(value=RUNTIME)
#Documented
#Constraint(validatedBy={})
public #interface NotNull
javax.annotation.Nonnull
#Documented
#TypeQualifier
#Retention(value=RUNTIME)
public #interface Nonnull
Usage:
So feel free to use any one of these four on your method.
you can use .OrElse(). See this example
Optional<String> response = Optional.of("Not Null");
Optional<String> response2 = Optional.empty();
System.out.println(response.orElse(""));
System.out.println(response2.orElse("Dont want to return null"));
Is there any way to implement annotation in order to change his parameter value by itself?
For example:
I would like create custom RequestMapping annotation to get rid of some code duplicates.
Current code:
#RequestMapping("/this/is/duplicate/few/times/some")
public class SomeController {
}
And I want to create something like this
#Retention(RetentionPolicy.RUNTIME)
#RequestMapping()
public #interface CustomRequestMapping {
String value() default "";
#AliasFor(annotation = RequestMapping.class, attribute = "value")
String "/this/is/duplicate/few/times"+value();
}
In order to reduce Request Mapping value to this:
#CustomRequestMapping("/some")
public class SomeController {
}
Unfortunately I cant find way to make that compilable.
Or maybe there is a way to use AliasFor annotation to pass parameter into destination array. Something like this:
#Retention(RetentionPolicy.RUNTIME)
#RequestMapping()
public #interface CustomRequestMapping {
#AliasFor(annotation = RequestMapping.class, attribute = "value{1}")
String value() default "";
#AliasFor(annotation = RequestMapping.class, attribute = "value{0}")
String prefixPath() default "/this/is/duplicate/few/times";
}
What it seems is you are trying to make a subtype of an annotation and modify one of its attributes default value
Subtyping of annotation is not possible and here is the JSR stating the reason.
It complicates the annotation type system,and makes it much more difficult
to write “Specific Tools”.
“Specific Tools” — Programs that query known annotation types of arbitrary
external programs. Stub generators, for example, fall into this category.
These programs will read annotated classes without loading them into the
virtual machine, but will load annotation interfaces.
One solution to your duplication problem could be to extract a constant.
#Annotation(MyClass.FOO+"localValue")
public class MyClass
{
public static final String FOO = "foo";
...
}
When we create a custom annotation, we declare elements as methods and later set values as if they were attributes.
For example, here we have declared a custom annotation ComponentType with elements name() and description() that look like methods.
public #interface ComponentType {
String name();// declared as method
String description();
}
When the annotation is used, they look like the below:
#ComponentType(name = "userContainer", // value looks like an attribute
description = "a user container")
public class UserEntity { }
My question is: Why doesn't Java allow to declaring elements as attributes, like this?
public #interface ComponentType {
String name; // Compilation Error
String description;
}
If the properties of an annotation weren't defined as abstract methods in an interface, they would have been members. Something like:
public #interface ComponentType {
String name;
String description;
}
However, all the members in an interface are implicitly final (and static) and the above code does not compile, because name and description aren't initialized.
But if they were actually initialized with some values:
public #interface ComponentType {
String name = "name";
String description = "description";
}
then snippets like the following one wouldn't have been possible:
#ComponentType(
name = "userContainer" //cannot assign a value to a final variable
, description = "a user container")
My observation is:
Java consider annotations as special type of interface so:
Like interface we can declare only final attributes in an annotation:
String appName = "test application";//final attribute, never reset value
Annotation may contains only abstract methods(a method that is declared without an implementation).
public #interface ComponentType {
String name();// declared as abstract method
When we annotated elements(e.g. class, method, attribute) by annotation we need to set return value of those abstract methods, which looks like attribute but actually acts as an implementation.
#ComponentType(name = "userContainer"//set return value of method name()
We can use the values we set during annotated elements(e.g. class, method, attribute) by simply calling abstract methods of annotation.
Annotation annotation = annotatedClassObject.getAnnotation(ComponentType.class);
ComponentType componentType = (ComponentType) annotation;
String someName = componentType.name(); //returns value set during annotating
So like as interface,
Annotation never support to declare any non-final attributes.
Annotation may contains some abstract methods and we need to set return value of
abstract method during annotated elements(e.g. class, method,
attribute).
Expecting More Feedback / Answer
I'm creating some custom annotations. I need to create someones with "place-holders" as it is used in Spring
#Value("#{aParameter}")
or in JSF 2
#ManagedProperty(value="#{aParameter}")
I suppose that I must have a mapping somewhere (.properties or .xml file or an enum class) but I need to know to code this approach in custom annotation interface. I mean how to declare a place-holder in the annoatation interface ? and how to ensure the assignement of its value (in mapping file) when applying the annotation somewhere?
Thanks in advance.
You don't do it in the annotation declaration - you do it in the code using that annotation.
For example the #Value is declared like this:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public #interface Value {
/**
* The actual value expression: e.g. "#{systemProperties.myProp}".
*/
String value();
}
and if you trace how it's used you'll see that in org.springframework.web.bind.annotation.support.HandlerMethodInvoker class the value is fetched directly from the annotation defaultValue = ((Value) paramAnn).value(); and then resolved like this:
if (defaultValue != null) {
args[i] = resolveDefaultValue(defaultValue);
}
...
class AnnotationMethodHandlerAdapter{
...
protected Object resolveDefaultValue(String value) {
if (beanFactory == null) {
return value;
}
String placeholdersResolved = beanFactory.resolveEmbeddedValue(value);
BeanExpressionResolver exprResolver = beanFactory.getBeanExpressionResolver();
if (exprResolver == null) {
return value;
}
return exprResolver.evaluate(placeholdersResolved, expressionContext);
}
So the logic taking care of resolving properties and such is placed in classes
that actually use read annotations and make them useful.
I have a GSON annotation ("SerializedName") which I want to translate from my custom annotation. I mean, if I have "Serial" annotation with "SerialType" element (which tell me what the serialization type I want for the field), after setting the GSON type in the "SerialType" - how can I generate the GSON annotation for the specific field?
Example code:
#Target(ElementType.FIELD)
public #interface Serial
{
SerialType type();
String value();
}
public class Example
{
#Serial(type = SerialType.GSON, value = "test")
public int field;
}
will generated to:
public class Example
{
#SerializedName("test")
public int field;
}
Try looking at annotation processors. You can find more info in the docs
Here is a good post describing how to use them.