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()
}
Related
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.
I want to mark a field of a class with my custom annotation. And whenever any method is invoke I want to do some modification on that field.
public class Message{
public Integer id;
#FreeText // this is my custom annotation
public String htmlMsg;
public String textMsg ;
}
This annotation (#FreeText) can be used in any class.
In seasar framework, I can do this by create an interceptor and override invoke method. The I can get the object of this class and the find the field that marked with my annotation and modify it. However, i cannot find a way to do it in Spring.
In spring, I found some method like MethodInvocationInterceptor, but I don't know how to implement it. Can you suggest any way to do this in Spring?
Seasar2 and Spring are very close. I have not tested but you can do something like this.
First create FreeText custom annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
#Documented
public #interface FreeText {}
Then create the following interceptor
public class EncryptSensitiveDataInterceptor extends MethodInterceptor {
#Override
public Object invoke(MethodInvocation in) throws Throwable {
Object[] params = in.getArguments();
Object param = params[0];
for (Field field : param.getClass().getDeclaredFields()) {
for (Annotation anno : field.getDeclaredAnnotations()) {
if (anno instanceof FreeText) {
field.set(param, [YOUR CUSTOM LOGIC METHOD]);
}
}
}
return in.proceed();
}
Hope this help.
I'm using custom type use annotation. I can't read them from an object like any other regular annotation:
public class TestingAnnotations {
public static void main(final String[] args) {
final #CustomAnnotation TypeAnnotated b = new #CustomAnnotation TypeAnnotated();
System.out.println(b.getClass().getAnnotation(CustomAnnotation.class)); //<-- prints null :(
}
}
#Target({ElementType.TYPE_USE, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#interface CustomAnnotation {
}
class TypeAnnotated {
}
So, how can I check b instance is annotated?
Thanks
you are actually not annotating the class.... a class is annotated when it looks like:
#CustomAnnotation
class TypeAnnotated {
}
after that you will get the annotation doing:
TypeAnnotated b = new TypeAnnotated();
System.out.println(b.getClass().getAnnotation(CustomAnnotation.class));
It looks like you actually want a local variabel annotation
#Target({ElementType.TYPE_USE, ElementType.LOCAL_VARIABLE})
public #interface CustomAnnotation {
}
Then this compiles just fine:
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).
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"