How to find the first declaring method for a reference method - java

Suppose you have a generic interface and an implementation:
public interface MyInterface<T> {
void foo(T param);
}
public class MyImplementation<T> implements MyInterface<T> {
void foo(T param) {
}
}
These two types are framework types I provide. In the next step I want allow users to extend that interface as well as redeclare foo(T param) to maybe equip it with further annotations.
public interface MyExtendedInterface extends MyInterface<Bar> {
#Override
void foo(Bar param);
// Further declared methods
}
I create an AOP proxy for the extended interface and intercept especially the calls to furtherly declared methods. As foo(…) is now redeclared in MyExtendedInterface I cannot execute it by simply invoking MethodInvocation.proceed() as the instance of MyImplementation only implements MyInterface.foo(…) and not MyExtendedInterface.foo(…).
So is there a way to get access to the method that declared a method initially? Regarding this example is there a way to find out that foo(Bar param) was declared in MyInterface originally and get access to the accoriding Method instance?
I already tried to scan base class methods to match by name and parameter types but that doesn't work out as generics pop in and MyImplementation.getMethod("foo", Bar.class) obviously throws a NoSuchMethodException. I already know that MyExtendedInterface types MyInterface to Bar. So If I could create some kind of "typed view" on MyImplementation my math algorithm could work out actually.
Additional info:
I create the proxy for the MyExtendedInterface as follows:
ProxyFactory factory = new ProxyFactory();
factory.setTarget(new MyImplementation());
factory.setInterfaces(new Class[] { MyExtendedInterface.class });
factory.addInterceptor(new MyInterceptor(MyExtendedInterface.class));
The interceptor pretty much scans the methods and executes JPA queries for all methods declared in MyExtendedInterface but routes all method invocations of methods declared in MyInterface to the proxy target. This works as long as methods from MyInterface are not redeclared as the target then doesn't implement it anymore.
public class MyInterceptor implements MethodInterceptor {
public Object invoke(final MethodInvocation invocation)
throws Throwable {
// handling of query methods
// else
invocation.proceed();
// ^^ works if not redeclared but not if
}
}
So what I would like to do instead of invocation.proceed() is detect the method that originally declared the one being invoked and invoke that on the target manually.

Okay, here's the solution I came up with: As I know the base class and it generics structure (what T means in this case) as well as MyExtendedInterface types MyInterface to Bar I can scan the base implementation for possible matches as follows (pseudocode):
for all methods {
skip those with non matching name and parameters length;
for all generic parametertypes {
if typename = T then concrete type has to be Bar
...
}
}
I don't need a generic solution in this case so that seems to work.

The whole scenario seems strange. You can't apply AOP declared on MyExtendedInterface to MyImplementation, because it does not implement it.
Second, I don't understand why it matters which interface defines a method, since it is the implementation that the method is invoked on.
Apart from that, you can get all the methods declared by a certain class/interface by getDeclaredMethods(). Then you can iterate on them and find something that matches your criteria (name)

Related

Kotlin Conflicting overloads: public open fun statements()

I have an interface Persistable which looks like this, the <T extends Statement<T>> List<Statement<T>> is to allow it to support both BoundedStatements and SimpleStatements in data stax 4.x driver.
public interface Persistable {
<T extends Statement<T>> List<Statement<T>> statements();
}
This java interface is inherited by Kotlin class A such that
data class UpdateRule(
private val something: S) : Persistable {
override fun statements(): List<Statement<BoundStatement> {
return PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements() //this returns BoundStatement
}
}
However, this gives the error Conflicting overloads.This code seems to work in Java(although with a warning), but in Kotlin it does not allow at all, how can I resolve this while also making sure parent interface remains generic to both Bound and Simple Statement?
You seem to misunderstand what the generics in Persistable mean. As it is written right now, you are supposed to implement the statements method so that it can handle any kind of T that extends Statement<T>. The generics there doesn't mean "implement this by choosing a kind of statement that you like".
It only produces a warning in Java because Java's generics is broken. Because of type erasure, List<Statement<BoundStatement> and List<Statement<T>> both erase to the same type - List, so the method in UpdateRule does implement the method in the interface if you consider the erasures. OTOH, type erasure isn't a thing in Kotlin (at least not in Kotlin/Core).
To fix this, you can move the generic type parameter to the interface:
public interface Persistable<T extends Statement<T>> {
List<Statement<T>> statements();
}
data class UpdateRule(private val something: S) :
Persistable<BoundStatement> {
override fun statements(): List<BoundStatement> =
PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements()
}
Notice how when we are implementing the interface, we can now specify the specific T that we are implementing for.
In Java just like in Kotin, the value of the type parameter of a generic method is determined by the caller of the method, and can be different at every call of the method, even on the same instance.
In your specific case, with the Java interface declared like this, statements() is supposed to be implemented in such a way that the caller can choose which type of statement will be returned by a given call to this method. This is not the case in your implementation, and that's why Kotlin doesn't allow it. As pointed out by #Sweeper, Java is broken in this respect and might let you get away with a warning.
This is different when using a generic class or interface. If you define the type parameter at the class/interface level, then the value of that type parameter is determined at construction time of the class, or can be fixed by subclasses. For a given instance, all calls to the method will return a well known type, which is (I believe) what you want here.
You can do this in Java:
public interface Persistable<T extends Statement<T>> {
List<Statement<T>> statements();
}
And then in Kotlin:
data class UpdateRule(
private val something: S
) : Persistable<BoundStatement> {
override fun statements(): List<BoundStatement> {
return PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements() //this returns BoundStatement
}
}

Java GenericClass< ? extends Interface> as a Parameter

public interface A {}
public interface B {}
public class Test implements A{}
public class Test2 {}
I made a method which checks if a class implements an interface. I want my method to only accept generic interfaces and not all class objects.
method
public static boolean containsInterface(Class clazz, Class intf)
{
try
{
Validate.isTrue(intf.isInterface());
if(clazz.isInterface())
return JavaUtil.isClassExtending(intf, clazz);
for(Class c : ClassUtils.getAllInterfaces(clazz))
{
if(JavaUtil.isClassExtending(intf, c))
return true;
}
}
catch(Throwable t)
{
t.printStackTrace();
}
return false;
}
Since Test.class & Test2.class are not interfaces on the 2d parameter I want it to have a compile error since the 2d parameter must be an interface class
containsInterface(Test.class, Test.class);
containsInterface(Test.class, Test2.class);
acceptable use of my method
containsInterface(Test2.class, A.class);
containsInterface(Test.class, B.class);
what I tried
public static boolean containsInterface(Class clazz, Class<? extends Interface> intf)
I currently check if the class in the parameter is an interface then throw an exception. I would rather force people to not be able to call the method to begin with if it's not an interface
I am aware of Annotations and Enum objects are available to use as a class signature to make sure people are using the parameters right but, I can't seem to find the one for the interface itself.
I was told generics do not support interfaces or abstract classes type is this true even in jre 9-13+
You cannot force argument to be ANY interface implementation using type control system. The same would apply if you would like to eg force only Class<?> with abstract modifier. I am not sure if that is really needed as doing simple type isInterface assert is
Straigthforward
Clean
Robust
Easy to understand
Error prone
Testable
JDK Engineers does not care about that either. As an perfect example of such mechanism would be used (but there is none) is JDK Dynamic Proxy creation. You can create only create proxy of an interface (or set of) but not of class.
I don't think that it is just worth of the effort to write own preporocessors. Moreover it would be not universal - as you assume that runtime type must be know at compile time - what about dynamically loaded classes etc?
Intefaces in java has no super class that you can use in generic mode.
If you try get the super class of an interface with reflection returns null.
public static void main (String [] args) {
System.out.println(A.class.getSuperclass());
}
interface A {}
Output:
null

Generic Anonymous Inner Class Instantiation

I'm reading up on WebSocket Endpoints in Java EE and I came accross this
public class EchoEndpoint extends Endpoint {
#Override
public void onOpen(final Session session, EndpointConfig config) {
session.addMessageHandler(new MessageHandler.Whole<String>() {
#Override
public void onMessage(String msg) {
try {
session.getBasicRemote().sendText(msg);
} catch (IOException e) { ... }
}
});
}
}
This part,
new MessageHandler.Whole<String>() {....
Is Whole a generic Inner class? And since we are specifying String as a type parameter, onMessage accepts Strings? This looks really weird to me, we could just subclass Whole, and Override onMessage and that would be a different class. Then we could pass that with the type parameter to addMessageHandler right? But here, we are just overriding it and specifying the type parameter at the same time here right?
EDIT
So I have learned MessageHandler is an interface with two nested interfaces in it
MessageHandler.Whole<T> and
MessageHandler.Partial<T>
Now we pass an object of the type MessageHandler into the method addMessageHandler, how could it know that this object implements the onMessage method. It's not supposed to know, because this method is in the nested interface Whole.
Is Whole a generic Inner class?
No. It's a generic nested class (interface, to be precise), as the javadoc shows. The term "inner" is for non-static nested classes, which implicitly have a reference to an instance of their owning class. See the tutorial.
And since we are specifying String as a type parameter, onMessage accepts Strings?
Correct, as the javadoc shows.
we could just subclass Whole, and Override onMessage and that would be a different class
That's exactly what this code is doing. It creates and instantiates an anonymous subclass os Whole.
Now we pass an object of the type MessageHandler into the method addMessageHandler, how could it know that this object implements the onMessage method. It's not supposed to know, because this method is in the nested interface Whole.
As the javadoc shows, the interface Whole extands the interface MessageHandler. That's why you can pass a Whole to a method which expects a MessageHandler (just like you could pass a Banana to a method expecting a Fruit, because Banana is a Fruit).

Java polymorphism through injection at runtime

I hear that in Java I can achieve polymorphism through injection at runtime. Can someone please show a simple example of how that is done? I search online but I can't find anything: maybe I am searching wrong. So I know about polymorphism through interface and and extension such as
class MyClass extends Parent implements Naming
in such case I am achieving polymorphism twice: MyClass is at once of type Parent and Naming. But I don't get how injection works. The idea is that I would not be using the #Override keyword during injection. I hope the question is clear. Thanks.
So the end result here, per my understanding, is to change the behavior of a method through injection instead of by #Override it during development.
So I know about polymorphism through interface and and extension such as
class MyClass extends Parent implements Naming
This is known as inhertiance and not polymorphism. MyClassis a Parent and MyClass is also a Naming. That being said, inheritance allows you to achive polymorphism.
Consider a class other thanMyClass that also implements Naming :
class SomeOtherClass implements Naming {
#Override
public void someMethodDefinedInTheInterface() {
}
}
Now consider a method that takes a Naming argument somewhere in your code base :
public void doSomething(Naming naming) {
naming.someMethodDefinedInTheInterface();
}
The doSomething method can be passed an instance of any class that implements Naming. So both the following calls are valid :
doSomething(new MyClass());//1
doSomething(new SomeOtherClass());//2
Observe how you can call doSomething with different parameters. At runtime, the first call will call someMethodDefinedInTheInterface from MyClass and the second call will call someMethodDefinedInTheInterface from SomeOtherClass. This is known as runtime-polymorphism which can be achieved through inheritance.
But I don't get how injection works. The idea is that I would not be using the #Override keyword during injection
That's true in the broader sense. To inject something into a class, the class should ideally favor composition over inheritance. See this answer that does a good job in explaining the reason for favoring composition over inheritance.
To extend the above example from my answer, let's modify the doSomething method as follows :
public class ClassHasANaming {
private Naming naming;
public ClassHasANaming(Naming naming) {
this.naming = naming;
}
public void doSomething() {
naming.someMethodDefinedInTheInterface();
}
}
Observe how ClassHasANaming now has-a Naming dependency that can be injected from the outside world :
ClassHasANaming callMyClass = new ClassHasANaming(new MyClass());
callMyClass.doSomething();
If you use the Factory pattern, you can actually chose which subclass gets instantiated at runtime.
Do you think we could have done what we did above using inheritance?
public class ClassIsANaming implements Naming {
public void doSomething() {
someMethodDefinedInTheInterface();
}
#Override
public void someMethodDefinedInTheInterface() {
//....
}
}
The answer is No. ClassIsANaming is bound to a single implementation of the someMethodDefinedInTheInterface method at compile time itself.
`
Taking a contrived example. You have a class Store that stores things:
class Store {
private List l
void store(Object o) {
l.add(o);
}
void setStoreProvider(List l) {
this.l = l
}
}
You can inject the actual List used as the backing storage using setStoreProvider which could be a linked list, array backed list, whatever.
Hence, depending on the injected type your Store class would have the features of the injected type (with regards to memory usage, speed, etc).
This is a kind of polymorphism without the class implementing an interface.

How to force putting a object into a handler class

I already post some relevant code in this question:
Specify object type of a returned array list dynamically
Now my question is a little bit more specific.
In fact I am using the following "handler" class to invoke methods of classes which implement the interface IMSSQLStatement:
public class MSSQLHandler {
IMSSQLStatement statement;
public MSSQLHandler(IMSSQLStatement statement) {
this.statement = statement;
}
public void invoke() throws SQLException {
statement.executeStatement();
}
public List<?> getDataList() throws SQLException {
return statement.getDataList();
}
}
The question is now how to force me (or an developer which implements my interface) to put created objects of the implemented class to MSSQLHandler?
Maybe this is bad design but I did not find any information and use cases regarding my problem.
Yes, you can use an abstract class with an explicit constructor, that is automatically called on all subclasses:
public abstract class IMSSQLStatement {
protected IMSSQLHandler handler;
public IMSSQLStatement() {
handler = new IMSSQLHandler(this);
}
}
Edit: (in reference to comment)
If you want that only the handler should be able to call the methods in IMSSQLStatement, both classes should be placed in the same package. Allow only package-private and subclass access, by giving the protected modifier. Although the methods could be called in the subclass itself, it would not be accessible outside, with the exception of the package.
This won't solve your problem completely. The other (real bogus) way around would be reflection.
To use reflection, you should write in your documentation the exact method signature the subclass should use (of course, don't define an abstract method in the superclass), giving it the private modifier. The handler should access these methods through reflection.
Refer some document, that describes how to use reflection. This is complicated, and beyond the scope of SO.

Categories

Resources