Hi! I’m new to Kotlin, and I’m facing a problem when trying to convert some code from Java. Let’s say I have a following hierarchy:
interface SomeDto interface SubDto : SomeDto
interface InterfaceA<T : SomeDto> {
fun method(param: T)
}
interface InterfaceB : InterfaceA<SubDto> {
@PreAuthorize("hasRole('some role')")
override fun method(param: SubDto)
}
public interface InterfaceBJava extends InterfaceA<SubDto> {
@Override
@PreAuthorize("hasRole('some role')")
void method(@NotNull SubDto param);
}
Then I create proxies for both Java and Kotlin interface, call this method and try to get declared annotations:
InterfaceA<SomeDto> proxyKotlin = (InterfaceA<SomeDto>) Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class[]{InterfaceB.class}, (proxy1, method, args1) -> {
System.out.println("Method " + method + " called, arguments: " + Arrays.toString(args1));
System.out.println("Annotations:" + Arrays.toString(method.getDeclaredAnnotations()));
return null;
});
InterfaceA<SomeDto> proxyJava = (InterfaceA<SomeDto>) Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class[]{InterfaceBJava.class}, (proxy1, method, args1) -> {
System.out.println("Method " + method + " called, arguments: " + Arrays.toString(args1));
System.out.println("Annotations:" + Arrays.toString(method.getDeclaredAnnotations()));
return null;
});
SubDto dto = new SubDto() {};
proxyKotlin.method(dto);
proxyJava.method(dto);
But for some reason the results are different for Java and Kotlin interfaces:
Method public abstract void InterfaceA.method(dto.SomeDto) called, arguments: [Main$1@27973e9b] Annotations:[] Method public default void InterfaceBJava.method(dto.SomeDto) called, arguments: [Main$1@27973e9b] Annotations:[@org.springframework.security.access.prepost.PreAuthorize(value=hasRole('some role'))]
If I change proxy types to InterfaceB and InterfaceBJava, the results are same
I have two questions:
- Why the method of super interface is passed to proxy?
- How to get annotations from InterfaceB?
In my case this situation occurs, when some Spring bean implements InterfaceB, and is called from another bean:
@Autowire
InterfaceA bean;
bean.method(dto)
Because no @PreAutorize is found, method is always called no matter what role is. If bean implements InterfaceBJava, everything works.
Tried with Kotlin 1.3.50 and 1.3.70, Java 1.8.0_231