I am using Java7. I have a custom annotation created and annotated it on an Marker interface.
#SomeName(name="ABC")
public interface Bank{
}
Below is the class which implements the above interface.
public class BankImpl implements Bank{
//some code
}
Now i have a method in a separate class which takes above class as an input:
public void someMethod(Class class){
//Here i need to get the custom annotation value
}
Above method is called as below:
someMethod(BankImpl.class);
Now inside someMethod() how can i get the annotation value?
Thanks!
String someMethod(Class<Bank> clazz){
SomeName sn = clazz.getAnnotation(SomeName.class);
return sn.name();
}
You only need the Class of the inteface to get everything of the Annotation which is annotated on the interface.
The problem is that the class itself does not have the annotation, therefore you'll get a null value when asking for the annotation. You really need to look into all the hierarchy of the class (i.e. superclass and interfaces):
import java.util.*;
import java.lang.annotation.*;
#Retention(value=RetentionPolicy.RUNTIME)
#interface SomeName {
String name();
}
#SomeName(name = "ABC")
interface Bank {
}
class BankImpl implements Bank {
}
public class Test {
public void someMethod(Class c) {
Annotation annotation = c.getAnnotation(SomeName.class);
if (annotation == null) {
LinkedList<Class> queue = new LinkedList<Class>();
queue.addLast(c.getSuperclass());
for (Class cc : c.getInterfaces())
queue.addLast(cc);
while (!queue.isEmpty()) {
c = queue.removeFirst();
annotation = c.getAnnotation(SomeName.class);
if (annotation != null)
break;
}
}
if (annotation == null)
System.out.println("No such annotation !");
else
System.out.println("name is: " + ((SomeName)annotation).name());
}
public static void main(String... args) {
Test test = new Test();
test.someMethod(BankImpl.class);
}
}
Related
I have a utility class OldRemote which has been deprecated now, but still it will be used for a while till the new class NewRemote is stable. And both the utility classes has the same method names and parameters, But the return type pojo classes are different. Even return type pojo structure is same, but naming is different.
In simple, both the function return types are pojo's with different field names.
Is there any generic way to handle this below usecase ?
I have created a service interface which has the generic method contract of both old and new class.
public interface RemoteService {
//contract [ return type is object to receive all/any Pojo classes ]
Object turnOnTV();
static Service GetRemoteservice(boolean isOldRemote){
if(isOldRemote){
return new OldRemote();
}
return new NewRemote();
}
}
OldRemote Class
public class OldRemote implements RemoteService{
#Override
public OldPojo turnOnTV() {
OldPojo oldPojo = new OldPojo();
System.out.println("OldPojo");
return oldPojo;
}
}
NewRemote Class
public class NewRemote implements Service{
#Override
public NewPojo turnOnTV() {
NewPojo newPojo = new NewPojo();
System.out.println("NewPojo");
return newPojo;
}
}
Demo usage of above implementation.
public class DemoTvRemote {
public static void main(String[] args) {
RemoteService remoteService1 = RemoteService.GetRemoteservice(true);
OldPojo oldRemote = (OldPojo) remoteService1.turnOnTV();
RemoteService remoteService2 = RemoteService.GetRemoteservice(false);
NewPojo shr = (NewPojo) Service2.test();
}
}
This above code works fine. But the problem is I don't want to type cast in all the places where turnOnTV() is used in my entire code base. Even If I have to do that, I will have to write a condition to switch between OldPojo and NewPojo where ever the turnOnTV() is invoked.
Is there any way to solve this problem ?
You could create a base class or interface they both extend/implement.
public abstract class RemoteServiceBase<E> {
public abstract E turnOnTv();
}
public class NewRemoteService extends RemoteServiceBase<NewRemotePojo >{
public NewRemotePojo turnOnTv() {
return new NewRemotePojo();
}
}
public class OldRemoteService extends RemoteServiceBase<OldRemotePojo >{
public OldRemotePojo turnOnTv() {
return new OldRemotePojo();
}
}
This would still only work if you know the service type. Otherwise you work with the common generic type as one would expect.
We can deal with this with the following approach :
1) We can create a dummy POJO class in a common location with having the reference of both OldPojo and NewPojo as data members
public class CommonPojo {
OldPojo oldPojo;
NewPojo newPojo;
public void setOldPojo(OldPojo oldPojo){
this.oldPojo=oldPojo;
}
public void setNewPojo(NewPojo newPojo){
this.newPojo=newPojo;
}
public OldPojo getOldPojo(){
return oldPojo;
}
public NewPojo getNewPojo(){
return newPojo;
}
}
2)We can write a Utility method as follow which can give an object of commonpojo :
public class CommonRemote {
public static CommonPojo turnOnTv(Boolean isOldRemote){
CommonPojo commonPojo = new CommonPojo
if(isOldRemote){
OldPojo oldPojo =new OldPojo();
commonPojo.setOldPojo(oldPojo);
}else{
NewPojo newPojo =new NewPojo();
commonPojo.setNewPojo (newPojo);
}
}
}
3) Use this method as turnOnTv() as Follows :
public class DemoTvRemote {
public static void main(String[] args) {
CommonPojo remote1 = CommonRemote.turnOnTv(true);
OldPojo oldRemote = remote1.getOldPojo();
CommonPojo remote2 = CommonRemote.turnOnTv(false);
NewPojo newRemote = remote2.getNewPojo();
}
}
with this approach with little changes in code We can achieve your requirement without any typecasting.
I want to be able to annotate a class with a list of 2 types of annotations which are related in function, but are completely different in arguments. The order of this list matters though. I have tried looking for this already, but was unable to find any references to this (I was not sure what to call this).
Edit:
What I want to be able to do in the end:
//place holder for example (Abstract)
public #interface A {
}
#Target(PARAMETER)
public #interface B extends A {
//Gets stuff
Class type();
int key();
}
#Target(PARAMETER)
public #interface FlaggedListOfA extends A {
//List of A
A[] set();
}
//Goal is to have annotation that does this
#Target(METHOD)
public #interface ImportantFunc {
A[] dataForA() default {};
String[] names();
int property() default 0;
//etc.
}
//End goal:
public class SomeImportantClass {
#ImportantFunc(dataForA = {#B(...), #B(...}, ...)
public void doStuff() {
}
//So I can have an end goal of this (Order matters, may contain repeats,
//and has unknown length!)
#ImportantFunc(dataForA = {#B(...), #FlaggedListOfA(#B(...), #B(...))}, ...)
public void doStuffB() {
}
#ImportantFunc(dataForA = {#FlaggedListOfA(#B(...)), #FlaggedListOfA(#B(...), #B(...))}, ...)
public void doStuffC() {
}
#ImportantFunc(dataForA = {#FlaggedListOfA(#B(...), #FlaggedListOfA(#B(...), #B(...))), #B(...)}, ...)
public void doStuffD() {
}
}
Reflections to get all uses of ImportantFunc (Ex: 100 uses of it) in package and uses this data to choose which function to use. The annotation is to help with the reflection since once it gets the data from #ImportantFunc, it then converts it to input for a library which does the actual choosing of which function to execute (this is internal and can not be modified). This could also be achieved with much longer and more annoying ways, but I was hoping to use annotations to simplify the process of defining all of these functions.
Edit:
Another way this could be solved is finding a way to group two annotations together.
Being able to do this would not be completely ideal, but would definitely make this much more workable:
public #interface Example {
AnyTypeOfAnnotation[] set();
}
One kludgy way to do this is to actually make A be a union of B and C. This means it has all the fields of both B and C, but you only ever use it as either a B or a C.
Here's a working example.
import java.lang.annotation.*;
enum NoType {;}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface A {
Class<?> data() default NoType.class; // field from B
int dataA() default 0; // field from C
String dataB() default ""; // field from C
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface D {
A[] value() default {};
}
class Foo {}
class Bar {}
class Example {
#D({
#A(data = Bar.class),
#A(dataA = 5, dataB = "Bla"),
#A(data = Foo.class)
})
public static void main(String[] args) throws Exception {
for (A a : Example.class.getMethod("main", String[].class)
.getAnnotation(D.class).value()) {
if (a.data() != NoType.class) {
System.out.printf("B(%s)%n", a.data());
} else {
System.out.printf("C(dataA = %d, dataB = \"%s\")%n",
a.dataA(), a.dataB());
}
}
}
}
The output of that program is:
B(class Bar)
C(dataA = 5, dataB = "Bla")
B(class Foo)
Of course, it's not a very pretty solution, but it does work.
Not sure this would be sufficient for your use case:
public #interface A {
}
public #interface B extends A {
//Gets stuff
Class data();
}
public #interface C extends A {
//Gets different stuff related to same goal
int dataA();
String dataB();
}
public #interface D {
Class<? extends A>[] order();
}
#B(Bar.class)
#C(dataA = 5, dataB = "Bla")
#D(order = {B.class, C.class})
public class SomeImportantClass {
}
This method uses D annotation as a mean to retain annotation order. The bad part is that you cannot add multiple annotations of the same type.
There is another method that makes A, B and C into normal classes.
public abstract class AnnotationAttribute {
public abstract Class<?>[] getDataTypes();
public abstract Object[] getData();
}
public class B extends AnnotationAttribute {
#Override public Class<?>[] getDataTypes() {
return new Class<?>[] {Foo.class, Bar.class};
}
#Override public Object[] getData() {
return new Object[] {new Foo(), new Bar()};
}
}
public #interface D {
Class<? extends AnnotationAttribute>[] data() default {};
}
#D(data = {B.class});
public class Test {
}
This method requires you to create one class for one concrete attribute type. This is because annotations have to be compile-time constant, and referencing via Class requires you to define the class out in code.
I'm trying to code, for fun, a class that use an annotion with another annotation inside, but I don't understand how to code.
My code
First annotation
#interface FirstAnnotation {
String author();
}
Second annotation, contains the first annotation
public #interface SecondAnnotation {
FirstAnnotation inside();
int version();
}
Class with annotation
#FirstAnnotation(
author = "alessandro"
)
#SecondAnnotation(
version = 1,
inside = /*Compilation code: what code? FirstAnnotation, this??*/
)
public class GeneralClass {
/*
* a generic method
*/
public void method() {
System.out.println("method");
}
}
What I have to put in row with string Compilation code, as reference to actual value of FirstAnnotation in the class?
You class should be:
#SecondAnnotation(
version = 1,
inside = #FirstAnnotation(
author = "alessandro"
)
)
public class GeneralClass {
/*
* a generic method
*/
public void method() {
System.out.println("method");
}
}
How can I stub/mock a void method which populates some objects that would be used later.
class RequestHelper{
public void populateOrderRequestBody(String product,String quantity,String profile, OrderType orderType){
orderType.setProduct(product);
orderType.setQuantity(Integer.parseInt(quantity));
orderType.setUser(profile.getUserId());
} }
class ServiceClient{
RequestHelper rh;
public void docall(Order order){
OrderType orderType = FACTORY.CreateOrderType;
rh.populateOrderRequestBody(order.getProduct(),order.getQuantity(),order.getProfile(),orderType);
/**
* some other code
**/
}
public setRequestHelper(RequestHelper rh){
this.rh=rh;
}
public RequestHelper getRequestHelper(){
return this.rh;
}}
Now I want to test ServiceClient class which call RequestHelper to populate orderType object. How to stub the method of RequestHelper class.
In this particular case if no verification will be done to rh filed you just need a plain Stub - just to ensure no NullPointerException is thrown when testing the docall method. Mock will also be sufficient however is more advanced object and using it here is pointless. When it comes to Spy it's used to verify invocations on a real (in terms of not being mocked) object. Have a look at the example below - runs smoothly just with Stub:
#Grab('org.spockframework:spock-core:1.0-groovy-2.4')
#Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def 'spec'() {
given:
def service = new ServiceClient()
service.rh = Mock(RequestHelper)
when:
service.doCall(new Order())
then:
noExceptionThrown()
}
}
class Order {
String product
String quantity
String profile
}
class OrderType { }
class FACTORY {
static OrderType CreateOrderType = new OrderType()
}
class RequestHelper {
public void populateOrderRequestBody(String product, String quantity, String profile, OrderType orderType) {
orderType.setProduct(product);
orderType.setQuantity(Integer.parseInt(quantity));
orderType.setUser(profile.getUserId());
}
}
class ServiceClient {
RequestHelper rh;
public void doCall(Order order) {
OrderType orderType = FACTORY.CreateOrderType;
rh.populateOrderRequestBody(order.getProduct(), order.getQuantity(), order.getProfile(), orderType);
}
public setRequestHelper(RequestHelper rh){
this.rh=rh;
}
public RequestHelper getRequestHelper(){
return this.rh;
}
}
Very similar to Opal's answer but using a mock order..
class Test extends Specification {
def 'spec'() {
given:
def service = new ServiceClient()
def order = Mock(Order)
order.getProduct() >> 'product1'
order.getProfile() >> 'profile1'
order.getQuantity() >> 3
service.rh = Mock(RequestHelper)
when:
service.doCall(order)
then:
noExceptionThrown()
1 * rh.populateOrderRequestBody('product1',3,'profile1',FACTORY.CreateOrderType)
}
}
Note that this only works if the CreateOrderType.equals() will return true
A class for example Exam has some methods which has annotation.
#Override
public void add() {
int c=12;
}
How can I get the method name (add) which has #Override annotation using org.eclipse.jdt.core.IAnnotation?
You can use reflection to do so at runtime.
public class FindOverrides {
public static void main(String[] args) throws Exception {
for (Method m : Exam.class.getMethods()) {
if (m.isAnnotationPresent(Override.class)) {
System.out.println(m.toString());
}
}
}
}
Edit: To do so during development time/design time, you can use the method described here.
The IAnnotation is strongly misleading, please see the documentation.
To retrieve the Methods from Class that have some annotation. To do that you have to iterate through all methods and yield only those that have such annotation.
public static Collection<Method> methodWithAnnotation(Class<?> classType, Class<? extends Annotation> annotationClass) {
if(classType == null) throw new NullPointerException("classType must not be null");
if(annotationClass== null) throw new NullPointerException("annotationClass must not be null");
Collection<Method> result = new ArrayList<Method>();
for(Method method : classType.getMethods()) {
if(method.isAnnotationPresent(annotationClass)) {
result.add(method);
}
}
return result;
}
Another simple JDT solution employing AST DOM can be as below:
public boolean visit(SingleMemberAnnotation annotation) {
if (annotation.getParent() instanceof MethodDeclaration) {
// This is an annotation on a method
// Add this method declaration to some list
}
}
You also need to visit the NormalAnnotation and MarkerAnnotation nodes.