custom annotation on class and method - java

Is it possible that I put custom annotation on class and then it forceful the developer to put the annotation on method?
suppose I have three custom annotation
#Loggable
#MySQLLoggable
#CassandraLoggable
when I put #Loggble annotation on class , it forceful the developer to annotate its all methods either by #MySQLLoggable or #CassandraLoggable.
update me!
EDITED
#Loggable // Suppose I put this annotation on class
public class Service {
#MySQLLoggable //eclipse forceful the developer
//to put #MySQLLoggable or #CassandraLoggable on sayHello()
public String sayHello() {
return null;
}
}

use #interface
public #interface foo {
String str();
}
#foo(str = "str")
public class myClass{
}
edit
public #interface loggable {
#loggable1(method) #loggable2(method))
String foo();
}

Sorry if you want that IDE make developers use your custom annotations then you better read your IDE specification and possible customization. If you want that later on during execution your app will throw exceptions if methods are not annotated then you have to use reflection. Let's save you use Factory Pattern to create objects. So before create them you can check whether all methods are annotated and if not all then throw an exception. Again I believe you have to use reflection.. this is only one way!

Related

How to set a property value using Java custom annotation and Spring AOP?

I would like to use custom Java annotation to insert a value in a private class property using Spring AOP (and/or AspectJ). Quick example:
MyAnnotation.java:
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.FIELD })
public #interface MyAnnotation {
}
MyController.java:
public class MyControllerImpl implements MyController {
...
#MyAnnotation
private String var1;
#Override
public String getVarExample() {
// imagine this is a REST API that gets called on #GET
// request and returns a string
System.out.println(this.var1); // <-- I'd like this to be "helloworld"
// this is just for illustration
// of course, I will want to do
// something more meaningful with
// the 'var1' variable
return "ok"; <- unimportant for this example
}
...
MyAspect.java:
#Aspect
#Component
public class MyAspect {
#Pointcut("#annotation(com.mypackage.annotation.MyAnnotation)")
public void fieldAnnotatedWithMyAnnotation() {
}
#Around("fieldAnnotatedWithMyAnnotation()")
public Object enrichVar1(ProceedingJoinPoint pjp) throws Throwable {
// problem #1 - the program never enters here
// problem #2 - I need to figure out how to set up the var1 here
// to "helloworld" , how?
return pjp.proceed();
}
...
}
What would I like to happen?
I will call and get into the getVarExample() and after it returns I would like to see "helloworld" in console or log. I would like to somehow set the var1 to a custom value using AOP. Any property variable that will be annotated with #MyAnnotation will be set to "helloworld". I hope the example above is clear.
What have I tried?
I made sure there is no typo in the package names, also fiddled with different AOP advice annotations like #Around and #Before. I also tried different targets in the MyAnnotation and ended up with ElementType.FIELD which should be correct.
Can you help me to get it working?
I know this can be done, but couldn't find any working example online. Again, I would like to see 2 answers:
1. How to get the pointcut to trigger on MyController entrance? I want to catch a breakpoint inside the enrichVar1(..) method of the MyAspect class.
2. How can I modify the annotated var1 value inenrichVar1(..) method of the MyAspect class?
I don't know what I am doing wrong. Any help will be greatly appreciated. Thank you!
The AOP is set up correctly in my project. I know that because I am already using AOP for different things (logging for example).
Update #1:
Please, note there are not getters or setters for the var1 private variable. The variable will be only used within the MyControllerImpl. To illustrate this better I changed the return value of the getVarExample.
Like I said in my comment:
The pointcut designator #annotation() intercepts annotated methods, not annotated fields. For that, native AspectJ has get() and set(). I.e., the pointcut would also need to be changed if migrating to AspectJ. But I agree that sticking to Spring AOP and annotating getter methods instead of fields is probably enough here.
But because you insist that you want to keep the controller class unchanged, here is the native AspectJ solution. Please read chapter Using AspectJ with Spring Applications for how to configure that with #EnableLoadTimeWeaving and JVM parameter -javaagent:/path/to/aspectjweaver.jar.
In order to demonstrate that this solution really does work independently of Spring, I am using no Spring classes or annotations at all, only POJOs and native AspectJ. You can simply do the same within your Spring application. Please note that native AspectJ aspects do not need #Component annotations, in contrast to Spring AOP aspects.
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.FIELD })
public #interface MyAnnotation {}
package de.scrum_master.app;
public interface MyController {
String getVarExample();
}
package de.scrum_master.app;
public class MyControllerImpl implements MyController {
#MyAnnotation
private String var1;
#Override
public String getVarExample() {
System.out.println(this.var1);
return "ok";
}
}
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
MyController myController = new MyControllerImpl();
myController.getVarExample();
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class MyAspect {
#Pointcut("get(#de.scrum_master.app.MyAnnotation * *)")
public void fieldAnnotatedWithMyAnnotation() {}
#Around("fieldAnnotatedWithMyAnnotation()")
public Object enrichVar1(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp);
return "helloworld";
}
}
When running Application, the console log is going to be:
get(String de.scrum_master.app.MyControllerImpl.var1)
helloworld
The AspectJ manual explains the syntax of field get and set join point signatures and field patterns.
Note: I think that your use case might be a hack rather than a valid application design. You ought to refactor rather than hack into an application like this.
As it goes from Spring docs Spring AOP does support Spring beans' method execution join points. To make field access join points work you need to use AspectJ's backend with load time weaving for AOP.
But for your case it's not required to use field join points, you can put your annotation on the getter and this should work.

Conditional execution of a method using annotation

In java can I have conditional execution of a method using annotations?
I wish to have some system property set and based on that system property I wish to either execute or not execute a method (specifically ant script based JUnits) at runtime.
Please let me know if it's possible using the annotations.
I think that you can implement it in Java but I suggest you to take a look on Spring AOP - I believe that this is what you are looking for.
You can group tests by #Category and tell the running to include this category.
From http://alexruiz.developerblogs.com/?p=1711
public interface FastTests { /* category marker */ }
public interface SlowTests { /* category marker */ }
public class A {
#Category(SlowTests.class)
#Test public void a() {}
}
#Category(FastTests.class})
public class B {
#Test public void b() {}
}
#RunWith(Categories.class)
#IncludeCategory(SlowTests.class)
#ExcludeCategory(FastTests.class)
#SuiteClasses({ A.class, B.class })
public class SlowTestSuite {}
You can implement your own TestRunner or user AOP for this.
An annotation, in the Java computer programming language, is a form of syntactic metadata that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated.
Take a look at this
I'd write a simple custom test runner by extending BlockJUnit4ClassRunner. That runner would read a configuration from a system property or a configuration file to only run the defined tests. The simplest solution would be a blacklist to exclude selected methods, because the default behaviour of this (default!) runner is to run every test.
Then just say
#RunWith(MyTestRunner.class)
public void TestClass {
// ...
}
For the implementation, it could be sufficiant to just overwrite the getChildren() method:
#Overwrite
List<FrameworkMethod> getChildren() {
List<FrameworkMethod> fromParent = super.getChildren();
List<FrameworkMethod> filteredList = new ArrayList(filter(fromParent));
return filteredList;
}
where filter checks for every FrameworkMethod whether it should be executed or not according to the "blacklist", that has been created based on the property.

Can't Get Guice Method Interception to Work

I'm trying to print a "Hello, AOP!" message whenever Guice/AOP Alliance intercepts a method marked with a particular (custom) annotation. I have followed the official docs (a PDF that can be found here - AOP method interception stuff on pg. 11) and cannot get it to work, only compile.
First, my annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
#BindingAnnotation
public #interface Validating {
// Do nothing; used by Google Guice to intercept certain methods.
}
Then, my Module implementation:
public class ValidatingModule implements com.google.inject.Module {
public void configure(Binder binder) {
binder.bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Validating.class,
new ValidatingMethodInterceptor()),
}
}
Next, my method interceptor:
public class ValidatingMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Hello, AOP!");
}
}
Finally, the driver that attempts to make use of all this AOP stuff:
public class AopTest {
#Validating
public int doSomething() {
// do whatever
}
public static main(String[] args) {
AopTest test = new AopTest();
Injector injector = Guice.createInjector(new ValidatingModule());
System.out.println("About to use AOP...");
test.doSomething();
}
}
When I run this little test driver, the only console output I get is About to use AOP...... the Hello, AOP! never gets executed, which means the #Validating doSomething() method is never being intercepted the way the Guice docs show.
The only thing I can think of is the fact that in my Module implementation I am specifying the MethodInterceptor to bind to (as the 3rd argument to the bindInterceptor method) as being a new ValidatingMethodInterceptor(), whereas in that interceptor, I am only defining a required invoke(MethodInvocation) method.
Perhaps I am not wiring these two together correctly? Perhaps Guice doesn't implicitly know that the invoke method should be ran when an intercept occurs?!?!
Then again, not only have I followed the Guice docs, I have also followed several other tutorials to no avail.
Is there something obvious I am missing here? Thanks in advance!
Edit One other discrepancy between my code and the examples I followed, although small, is the fact that my invoke method (inside the interceptor) is not annotated with #Override. If I try to add this annotation, I get the following compile error:
The method invoke(MethodInvocation) of type ValidatingMethodInterceptor must override a superclass method.
This error makes sense, because org.aopalliance.intercept.MethodInterceptor is an interface (not a class). Then again, every example using Guice/AOP Alliance uses this #Override annotation on the invoke method, so it obviously works/compiles for some people...weird.
If you don't let Guice construct your object, it can't provide you an instance with the interceptor wrapped around. You must not use new AopTest() to get an instance of your object. Instead, you must ask Guice to give you one instance:
Injector injector = Guice.createInjector(new ValidatingModule ());
AopTest test = injector.getInstance(AopTest.class);
See http://code.google.com/p/google-guice/wiki/GettingStarted

Understanding annotation in Java

I was trying to go through some online material to learn annotation in java.
In the following code, what happened to my dear "Hello world" string which I passed in this line: #Test_Target(doTestTarget="Hello World !")?
#Target(ElementType.METHOD)
public #interface Test_Target {
public String doTestTarget();
}
above is the annotation defined and below is its usage
public class TestAnnotations {
#Test_Target(doTestTarget="Hello World !")
private String str;
public static void main(String arg[]) {
new TestAnnotations().doTestTarget();
}
public void doTestTarget() {
System.out.printf("Testing Target annotation");
}
}
When I run this code it is only printing Testing Target annotation
Please help me out, I am completely new to annotation.
Annotations are basically bits of data you can attach to fields, methods, classes, etc.
The syntax for declaring annotations in Java is a little awkward. They look a bit like interfaces (they are, after all, declared with #interface), but they aren't really interfaces. I think you might have put the doTestTarget() method in your TestAnnotations class because you thought your annotation was an interface and you needed to implement it. This isn't true - you can delete this method and the call to it from your code if you wish and doing so won't cause you any problems.
Also, you might not have intended to put the annotation on the field str. Annotations apply only to what immediately follows them. As a result, your code doesn't compile, because you've applied your annotation to a field but declared that your annotation can only be applied to methods. Change #Target(ElementType.METHOD) to #Target(ElementType.FIELD) and your code should then compile.
As for what happens to the string Hello World !, it gets written to the .class file and is available to any tool that reads in Java classes. However, it wouldn't necessarily be available in the JVM at runtime. This happens because you didn't specify a #Retention for your #Test_Target annotation. The default value for #Retention is RetentionPolicy.CLASS, which means that the JVM might not bother to load them out of the class file. (See the Javadoc for the RetentionPolicy enum.)
I imagine you want to see some way of reading the value out of this annotation at runtime. If so, I'd recommend adding #Retention(RetentionPolicy.RUNTIME) to your annotation to make sure it will be available at runtime.
To access your annotation and the value contained within it at runtime, you need to use reflection. I've rewritten your TestAnnotations class as follows to give a quick demonstration:
import java.lang.reflect.Field;
public class TestAnnotations {
#Test_Target(doTestTarget="Hello World !")
private String str;
public static void main(String[] args) throws Exception {
// We need to use getDeclaredField here since the field is private.
Field field = TestAnnotations.class.getDeclaredField("str");
Test_Target ann = field.getAnnotation(Test_Target.class);
if (ann != null) {
System.out.println(ann.doTestTarget());
}
}
}
When I run this code, it gives me the following output:
Hello World !
In principle, adding an annotation by itself does not fundamentally alter the programs behaviour.
In your case, you created a new annotation type #Test_Target, which can by used on any method (as indicated by its #Target annotation).
Then you applied this not to a method, but to the str field (which should give a compiler error, I think).
Independently of this, you are creating an object with a doTestTarget method, and invoke it, and get the expected result (i.e. the method is executed).
If you want your annotation to do something more than simply be there and provide some information for the reader of the source, you have to use it - either with an annotation processor at compile time, or using reflection on run time (then you would need also #Retention(RUNTIME) as an annotation on Test_Target.)
In the spirit of learning, another way is to use the annotated class without targeting a method or field.
First declare your interface with the method you need and Retention Policy to Runtime
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
public #interface Test_Target {
public String doTestTarget() default "default string";
}
then annotate the interface created to your class. From your class find the annotated class and then call the method with it.
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
#Test_Target(doTestTarget="Hello World !")
public class TestAnnotations {
public static void main(String[] args) throws Exception
{
AnnotatedElement c = TestAnnotations.class;
if(c.isAnnotationPresent(Test_Target.class))
{
Annotation singleAnnotation = c.getAnnotation(Test_Target.class);
Test_Target tt = (Test_Target) singleAnnotation;
System.out.println(tt.doTestTarget());
}
}
}
the result is:
Hello World !

Inject into private, package or public field or provide a setter?

I see many Java examples using dependency injection with private fields without a public setter like this:
public SomeClass {
#Inject
private SomeResource resource;
}
But that is a bad idea when the injection should be performed manually for example in unit tests.
There are several possibilities to solve this:
add a public setter: setSomeResource(SomeResource r)
make the field public
make the field package protected
I'd like to avoid the setter, since nothing really happens in it. So I'd prefer public or package protected. What do you recommend?
One way to avoid creating a setter for the field is using constructor injection. This even allows you to declare the field as final.
It goes like this:
public class SomeClass {
private final SomeResource resource;
#Inject
public SomeClass(SomeResource resource) {
this.resource = resource;
}
}
Adding setters is not an optimal solution, since you are adding production code which is not needed.
An alternative is to use Spring's ReflectionTestUtils class to inject your test dependencies using reflection, see http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html
EDIT (2017): However, reflection is an even worse solution than adding setters. The cause of this mess is the fact that Spring makes it possible to inject values without setters or constructors. My current stance is to stick to using either of those and avoid using black magic injection practices.
I prefer the setter
it is easier to debug (put a breakpoint in a setter rather than on field access / modification)
easier to log
easier to add some validation (although this is not always the best place)
easier to support bidirectional maintainance (though IOC container can take care of that)
any other "manual AOP" purpose
But that's just my opinion
I recommend using setter. In this question are the benefits of using getters and setters.
With the help of the answer to my (related to this one) question:
How do app servers inject into private fields?
I coded this simple example on how to inject without setters.
Perhaps it helps
//......................................................
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
With field based injection, you run into the issue you describe with testing. Also with setter based injection, an instance of a class can be created in an incomplete state when running tests if you forget to set some of the dependencies. I have been practicing constructor injection most recently due to the fact that it forces you to set all dependencies whenever you create an instance of a class during testing. The answer above by Andre Rodrigues explains how this would be accomplished.
Possible solutions to this:
Use a CDI-aware testing framework like JGlue CDI-Unit. This way you need no setter. You only define the dependency inside your tests - usually using a Mockito mock object. IMHO this is the best solution, since it doesn't require you to do anything extra for testing.
Inject into Constructor or setter. That's right, you can inject into setters! More details here.
Use a protected setter. Simple and works in every case. Since it's protected, you can access it from your test class (which should have the same package definition as your tested class), and no other packages can access it.
Use a getter and override it when testing. In your test class, create a new inner class that extends the tested class and override the getter. This, however, has a big disadvantage: your test class has to use the getter internally instead of the field. Lots of potentially bugged boilerplate...

Categories