creating custom annotation and using it in java? - java

I have written below the Custom Annotation.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {
String value();
}
and am using the annotation as below.
#MyAnnotation("someValue")
public void someMethod(){
}
above code is working fine without any issues.
But in the annotation class, value() method name i have to reanme. Can i do as below?
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {
String name();
}
I tried doing but eclipse is giving the compilation error.
- The attribute value is undefined for the annotation type
MyAnnotation
- The annotation #MyAnnotation must define the attribute
name
Any reason?

Use it like this :
#MyAnnotation(name="someValue")
public void someMethod(){
}
because by default annotation has value method so if you specify like this
#MyAnnotation("someValue")
public void someMethod(){
}
it will by default take it as value="someValue"

Related

How can I send annotation value into #Before method?

I want to change principal for a method annotated with my custom annotation.
I created my custom annotation:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface RunAsUser {
}
I've written special handler:
#Aspect
#Component
public class RunAsUserAnnotationHandler {
#Before("#annotation(RunAsUser)")
public void configureAuthentication() {
AuthenticationUtil.configureAuthentication("ROLE_USER");
}
#After("#annotation(RunAsUser)")
public void clearAuthentication() {
AuthenticationUtil.clearAuthentication();
}
}
where configureAuthentication(...) and clearAuthentication() are methods which set another hardcoded principal value to SecurityContext and return one to the default value.
How can I modify my code if I want to set principal value as String in annotation?
I want to see smth like this:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface RunAsUser {
String userName();
}
and write my code using RunAsUser("stackoverflowUser") but I do now know how to tranport this value to my configureAuthentication method from annotation.
Any advice?
Add an argument of type RunAsUser to your configureAuthentication() method. Get the value ("stackoverflowUser") out of this argument:
#Before("#annotation(runAs)")
public void configureAuthentication(RunAsUser runAs) {
// do something with runAs.value()
}

Have a common base type for all my custom annotations

So, I have created several custom annotations:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Foo {
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Bar {
}
Those annotations are used in my functions:
public class Worker {
#Foo
public void doTaskOne() {...}
#Bar
public void doTaskX() {...}
...
}
I want to use java reflection to check if certain annotation is declared in one method.
for (Method m : methods) {
if (m.isAnnotationPresent(Foo.class)) {
...
} else if (m.isAnnotationPresent(Bar.class)) {
...
}
}
The problem is that since in Java, custom annotation #interface is not able to be extended. I mean this is illegal:
public #interface Bar extends MyBaseAnnotation{
}
That's I am not able to have a base #interface for all my custom annotation class Foo and Bar. So, if I have a new custom annotation created, I need to add more else if condition in above method checking code, which sucks! Is there anyway to get rid of this problem? What I want to achieve is to generalize my method checking code to :
for (Method m : methods) {
if (m.isAnnotationPresent(MyBaseAnnotation.class)) {
...
}
}
How to achieve it?
You can annotate your custom annotations with a base custom annotation, like composed annotations do.
Instead of:
public #interface Bar extends MyBaseAnnotation{
}
use:
#MyBaseAnnotation
public #interface Bar {
}
Assuming that
#Parent
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface Foo {}
#Parent
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface Bar {}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.ANNOTATION_TYPE)
#interface Parent {}
and there is a method
public static boolean isAnnotationPresent(Method method, Class<? extends Annotation> parentAnnotation) throws NoSuchMethodException {
for (Annotation methodAnnotation : method.getDeclaredAnnotations()) {
if (methodAnnotation.annotationType().isAnnotationPresent(parentAnnotation)) {
return true;
}
}
return false;
}
you can do
isAnnotationPresent(m, Parent.class)
You got it right: there is no inheritance between annotation types in Java. You could make your own rules, though. By saying "if annotation B has annotation A over it, then B extends A", you define the rule that you will follow while using reflection.

My custom annotation with #Repeatable dont work when I annotated twice

I'm creating some annotations, and one of them I trying to enable to annotate twice. I use #Repeatable and created the conteiner. But when I use the annotation twice it appears that it needs to use #Repeatable.
As shown in the image below:
Message error: Duplicate annotation of non-repeatable type #TX2Value. Only annotation types marked #Repeatable can be used multiple times at one target.
#Repeatable(TX2ValueContainer.class)
#Retention(RUNTIME)
#Target({ FIELD, METHOD, ANNOTATION_TYPE, TYPE_USE })
public #interface TX2Value {
String name();
...
}
#Retention(RUNTIME)
#Target({ FIELD, METHOD, ANNOTATION_TYPE, TYPE_USE })
#interface TX2ValueContainer {
TX2Value[] value();
}
public void TestA() {
#TX2Value(name="test01")
#TX2Value(name="test02")
private String value;
}

Use #Parameters in TestNg on class level

The #Parameters annotation implementation from org.testng.annotations looks like this:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE})
public #interface Parameters {
String[] value() default {};
}
So, it should allow me to use it on a ElementType.TYPE => it could also be used on a class.
When I use it on a method, I simply take the value using:
#Parameters("value")
public void m(String value) {
...
}
But if I use
#Parameters("value")
public class A {
...
}
how can I get the value inside the class?
If you want to use it for initialising class variables you can put in on constructor of class and use it.
ElementType.TYPE also means applicable to interfaces and enums - may be that one is specified if you want to extend the annotation.

How to use custom class annotation in testng listener java

I created a method level java custom annotation like below
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Test {
public String id() default "0";
}
Test Class:
public class test {
#Test
#Test(id = "231")
public void test_section(){
Assert.assertTrue(false);
}
}
i was able to use the value of id using below code line
result.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).id();
Now i want to create a class level custom java annotation as below
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface section {
public String Name() default "0";
}
and use the same annotation in my test class and get the value of Name in the testng listener ITestListener onTestStart method as i am using testng to execute the test case, below is the test class
#section(Name="u_id")
public class testcustom {
#Test
public void test_section(){
Assert.assertTrue(false);
}
}
I am unable to get the value of section, How to get the value of name in section annotation used on class level?
Just looking at the API, something like
void onTestStart(ITestResult result) {
section annotation = result.getTestClass().getRealClass().getAnnotation(section.class);
if (annotation != null) {
// do something with annotation.Name()
}
}
should work (note that Java naming conventions mean it should be Section and name() instead).

Categories

Resources