I want to access Method via reflection. The problem is that the Method is annotated in an interface:
public interface MyRepository extends CrudRepository<MyClass, Long> {
#CustomAnnotation
MyClass findByName(String name);
}
As you see I use Spring which provides a class that will implement this Repository interface.
I want to create a method, that will get a Repository and invoke all methods that are annotated with #CustomAnnotation.
public void do(Repository<?, ?> repository){
Method[] methods=repository.getClass().getMethodThatAreAnnotatedInInterfaceWith(CustomAnnotation.class);
....
}
Because the implementation of an interface won’t have the annotations of the interface present, I do not know how to query these methods.
Since you are using Spring, use the AnnotationUtils#findAnnotation(Method method, Class<A> annotationType):
Find a single Annotation of annotationType on the supplied Method, traversing its super methods (i.e., from superclasses and interfaces) if the annotation is not directly present on the given method itself.
Iterate over the methods of getClass().get[Declared]Methods() and for each of them check if it is annotated with your annotation using the above utility.
Get the method of super class by repository.getClass().getDeclaredMethod().
Get the interface of class by repository.getClass().getInterfaces().
check the method of interface whether has the annotation.
One way to get a method's hierarchy would be to use Apache Commons Lang's class MethodUtils. Provided you get the implementation of a method you then can use that class to get (and check) the hierarchy of that method:
Set<Method> hierarchy = MethodUtils.getOverrideHierarchy( method, Interfaces.INCLUDE );
Then check the methods in that hierarchy for the annotation.
Alternatively you could check out the former Google Reflections library which has the method Reflections#getMethodsAnnotatedWith(SomeAnnotation.class). You'd then use the returned set to check whether the actual implementation is an instance of the class/interface declaring those methods.
Here s the solution:
for (Class c : r.getClass().getInterfaces()) {
for (Method m : c.getDeclaredMethods()) {
if (m.getDeclaredAnnotation(CustomAnnotation.class) != null) {
m.invoke(r, params);
}
}
}
Related
I need to create a custom classes based on some input. What I have atm is this:
final Class service = ...;
final Method method = ...;
final DynamicType.Unloaded unloadedType = new ByteBuddy()
.subclass(Object.class)
.name(service.getClass().getSimpleName() + "DynamicResolver")
.defineMethod(
endpointName,
resolveReturnType(method),
Modifier.PUBLIC)
.withParameters(parameters)
.intercept(MethodDelegation
.withDefaultConfiguration()
.withBinders(Morph.Binder.install(Morphing.class))
.to(interceptor).andThen(
MethodCall.invoke(method).on(service).withArgument(arguments)
))
.make()
What I am doing here is creating a class with a single method that delegates to provided one. However, the created method and delegate method have a bit different parameters. The created method has one argument more (in parameters). The created method does not take that argument, hence the arguments array with argument indexes (one argument less).
So far it's OK. Now, I need to add additional argument when calling delegation method. For the sake of simplicity of the example, imagine we have to add one more string to delegate call.
As I saw from the documentation, the way to manipulate the arguments is using #Morph. So I did:
public interface Morphing<T> {
T invoke(Object[] args);
}
and my interceptor:
public class Interceptor {
#RuntimeType
public Object invoke(
#Morph final Morphing<Integer> m,
#AllArguments final Object[] args
) {
System.out.println("!!!");
return m.invoke(args);
}
}
Unfortunately, this is not working. When I remove the #Morph argument, the interceptor gets called.
What am I missing here?
EDIT: Is the #Morph used only for subclasses and not when delegating to another instance?
EDIT2: example
Byte Buddy is binding a method of the Object class such that your desired interceptor is no longer triggered. You can add filter(isDeclaredBy(MyInterceptor.class)) after the withDefaultConfiguration() to avoid this. Doing so, you will get an exception that Byte Buddy cannot bind any of your methods.
The reason that #Morph makes the class ineligable is that there is no super method to be called. In your example, you are defining a new method which does not have an original implementation. You'd need to override an existing method to use the annotation.
Suppose I have two similar (but different) methods (or maybe static methods) create_x() and create_y() to create objects (call them x and y) both (of class derived) of class Parser.
Now I want to bind the objects created by these two methods like as in answer to my previous question:
bind(Parser.class)
.annotatedWith(Names.named("x"))
.to(ParserXImplementation.class);
bind(Parser.class)
.annotatedWith(Names.named("y"))
.to(ParserYImplementation.class);
but with object created by create_x(), create_y() instead of instances of classes ParserXImplementation, ParserYImplementation. (So that there is no necessity to create classes ParserXImplementation, ParserYImplementation.)
Note that I want the objects to be singletons.
I want the answers both for the case if create_x(), create_y() are static methods and for the case if they are instance methods. If they are instance methods, the class containing them may itself be subject to dependency injection.
How to do this? (injecting dependencies to instances created by methods)
From https://github.com/google/guice/wiki/ProvidesMethods:
When you need code to create an object, use an #Provides method. The method must be defined within a module, and it must have an #Provides annotation. The method's return type is the bound type. Whenever the injector needs an instance of that type, it will invoke the method.
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
...
}
#Provides
TransactionLog provideTransactionLog() {
DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
transactionLog.setJdbcUrl("jdbc:mysql://localhost/pizza");
transactionLog.setThreadPoolSize(30);
return transactionLog;
}
}
Further, it says that it can use annotation like #Named("x") and #Named("y") to differentiate x and y as described in the answer to Binding the same interface twice (Guice).
This is what I need (however the method is defined inside a module rather than in an arbitrary class).
I am clear with polymorphism and inheritance concept of oop, but I am in a situation where I need to know the implementing class. For example:
public CommonReadRepository<?> getReadRepository(String tableName) {
if (tableName == null)
return null;
switch (tableName) {
case "order":
return orderRepository;
...
}
return null;
}
The interface orderRepository extends CommonReadRepository, and because of my requirement, I need to access a function defined in orderRepository.
CommonReadRepository<?> repository=getReadRepository("order");
Is there any way to check back the implementing (child) class or interface of CommonReadRepository?
Of course, I can always do something like this:
if(tableName=="order")
return (OrderRepository)CommonReadRepository<?>;
I tried to debug getReadRepository("order"), but it gives me an instance of JdkDynamicAopProxy, and I am not sure how it works.
if(interface is instanceof xyz class)
i do not want to use it because i have 100 of classes and i want to keep it as a last resort... or in other words
i don't know about xyz class
Thanks
Following is one way to check if the returned Object is an instance of the specified class:
CommonReadRepository<?> repository=getReadRepository("order");
if(repository instanceof WhatEverSubclass) {
// do something
}
But using this approach is not how OOP is supposed to be done. If your classes all implement the same Interface, why don't you define a common method, that's then used in all the subclasses, but implement it differently every time.
I think, what you try to do is not getting you anywhere.
You can find all available classes inheriting an interface using the reflections tool (https://github.com/ronmamo/reflections). I used it for a dependency injector and it works very reliable.
Yet, why don't you just use the instanceof operator to make sure the object is of the right type:
if( repository instanceof OrderRepository) return (OrderRepository)repository;
But still, this won't change the return type of your function and you need to inspect the type of the returned value again outside of your function.
Update: If this happens for hundreds of objects, you could change the getRepository method to return a type you give as parameter: <T> getRepository(String name, Class<T> expectedType)
This will allow you OrderRepository o = getRepository("order", OrderRepository.class);
I want to provide an annotation as the following:
public #interface CloneField
{
String sourceField();
Class<?> customCloner();
}
Where people can annotation fields on their classes and some framework will automatically copy fields to their classes instances by running a method from the customCloner on an external data source object.
For example:
class Test {
#CloneField(sourceField = "demoTest", customCloner = StringToIntCloner.class)
private int testField;
This will copy a string value from a field named demoTest on the external data source object into an int field on the user's object.
Since the customCloner doesn't hold any data I would want to define the cloning method as static without the need to instantiate it just for calling a method.
Usually I would define the custom cloner class as:
Class <? extends FieldCloner> customCloner;
where FieldCloner has a method for cloning.
But since static methods are not supported on interfaces there isn't a clean way to do so.
Is there an elegant way to do so in Java 7?
Beside the problem of running the method which can be solved by reflection I want to verify at compile time that the customCloner class has the appropriate method for cloning.
If I have an OrderHandler interface:
public interface OrderHandler {
public void handle(Order order);
}
And have several implementations (DefaultOrderHandler, ComplexOrderHandler, SpecialOrderHandler, etc.) of it, how do I specify which one to use in Camel's SimpleRegistry? For instance, if I have the following route:
from("direct:pointA")
.bean(OrderHandler.class)
.to("direct:pointB");
How do I specify a SimpleRegistry, and how do I configure that registry to "inject" a DefaultOrderHandler when I specify a processor of type bean(OrderHandler.class)?
I ask because it would be nice (for unit testing) to be able to inject a DummyOrderHandler during testing, and a real impl during production. Thanks in advance!
When using
bean(MyClass.class)
Then usually the class type (eg MyClass.class) must be a class (not abstract, not interface) as Camel will use that to instantiate an instance.
However if the method that is being invoked is a static method, then Camel does not need to instantiate an object, and therefore the class can be abstract etc. You can supply the method name as a 2nd parameter to pint point which method to call.
In your case have 3 different implementations of an interface. You need to specify the type to use
bean(MyImpl.class)
Or refer to a bean by a name to lookup in the registry, or provide an object instance
For example:
OrderHandler handler = new DummyOrderHandler;
...
bean(handler)
As its just Java code, and if you are using RouteBuilder then you can juse have getter/setter for OrderHandler, and then set the desired implementation on RouteBuilder
RouteBuilder myBuilder = new MyRouteBuilder();
myBuilder.setOrderHandler(new DummyOrderHandler());
...
And then in the configure method in MyRouteBuilder you can use
bean(handler)