pyjnius java abstract class implementation - java

I am trying to implement android.bluetooth.le.ScanCallback which is an abstract class using pyjnius. The moment I instantiate the given below python class there is a JVM error. The error states that android.bluetooth.le.ScanCallback is not an interface class. I believe an interface is an abstract class. What am I missing?
class ScanCallback(PythonJavaClass):
__javainterfaces__ = ['android/bluetooth/le/ScanCallback']
def __init__(self, scanCallback, batchCallback=None, errorCallback=None):
super(ScanCallback, self).__init__()
self.batchCallbk = batchCallback
self.scanCallbk = scanCallback
self.errorCallbk = errorCallback
pass
#java_method ('(L/java/utils/List<ScanResult>/)V')
def onBatchScanResults(self,results):
print dir(results)
#java_method ('(I)V')
def onScanFailed(self, errorCode):
print "failed to scan" + str(errorCode)
raise ValueError(str(errorCode))
#java_method ('(IL/android/bluetooth/le/ScanResult)V')
def onScanResult(self, callbackType, result):
print dir(result)

I found out that with PyJNius it is only possible to implement interface class (pure abstract class) not an abstract class. "android/bluetooth/le/ScanCallback" is an abstract class not an interface class which was the case with earlier bluetooth API (< 21).

Related

How to check if a (type variable) Class<T> is implementing the Interface SomeInterface<T extends SomeInterface<T>>?

I'm working with JSON data and converting it into Java POJO class, then I built an interface like this:
public interface DataUtil<T extends DataUtil<T>> {
default T someDefaultFn() { ... };
}
And I used this interface for some POJO data class like:
public MyPoJo extends DataUtil<MyPojo> { ... }
And I get stuck when I to try check the type variable Class<FType> (a FieldType of any fields are declared inside T class) whether FType extends DataUtil<FType extends DataUtil<FType>> or not? I'm also trying to research the java.reflect package but did not find the expected answer. Can anyone help me to resolve this problem or find another design solution for this scenario?

Java extract generic type parameters with reflection from interface

I'm writing a custom Java annotation for processing CrudRepositories with Reflection in Java Spring. With the org.reflections.reflections library. I'm getting all interfaces annotated with my annotation as a class file like so:
Reflections reflections = new Reflections("basePackage");
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(MyAnnotation.class);
Only interfaces, which at some point extend JpaRepository are annotated with my #MyAnnotation at the class level.
My repository structure is as follows:
There are two cases,
first case:
public interface SomeRepo extends JpaRepository<SomeEntity, Long> {...}
the second case is composed out of a inheritance hierarchy:
public interface SuperClassRepo <T extends SomeRandomEntity> extends JpaRepository<T, String> {...}
public interface SubClassRepo extends SuperClassRepo<SubEntityOfSomeRandomEntity> {...}
My goal is now to extract the generic type parameters of the underlying JpaRepository.
I achieved to do that if the annotated class is a Java class, not an interface. How can I achieve the same for an interface? I guess I'm also having trouble because of the inheritance. I guess I have to get the "super class" until I reach the JpaRepository and then somewhat extract the generic type arguments.
Help is very much appreciated, thanks in advance
I found a solution by looking at the GenericsUtils#getParameterType as suggested:
private static Class<?> extractKeyFromRepository(Class<?> repository) {
ResolvableType currentType = ResolvableType.forType(repository);
ResolvableType resolvableType = currentType.getInterfaces()[0];
if (JpaRepository.class.equals(resolvableType.getRawClass())) {
ResolvableType[] generics = resolvableType.getGenerics();
ResolvableType generic = generics[1];
return generic.resolve();
} else {
return extractKeyFromRepository(resolvableType.toClass());
}
}
This works only because I ensure beforehand, that what I'm putting in this method is valid. I do it like so, also I pay attention that only one interface is extended, by extending more than one interface one has to figure out which of these interfaces is the JpaRepository:
if (!repository.isInterface()) {throw new IllegalArgumentException();}
if (!JpaRepository.class.isAssignableFrom(repository)) {throw new IllegalArgumentException();}

Implementing generated interface with JavaPoet

I would like to use JavaPoet to generate an interface and a class implementing this interface.
TypeSpec if = TypeSpec.interfaceBuilder("MyInterface")
.build();
TypeSpec cl = TypeSpec.classBuilder("MyClass")
.build();
But I am strugelling to tell JavaPoet that MyClass should implement MyInterface. The method addSuperinterface(TypeName) requires a type name and I didn't findout how to turn a TypeSpec into an TypeName. The only way I found is calling ClassName#get(String, String).
Is there an better way to achive this and to use the type specification for the interface directly?
It is not as complicated as it may seem.
The TypeSpec.Builder has two versions of the addSuperInterface method:
TypeSpec.Builder addSuperinterface(Type superinterface)
TypeSpec.Builder addSuperinterface(TypeName superinterface)
We could use the second version for example and obtain the super interface as an instance of the TypeName class using ClassName.get
One of the signatures of the get method of the ClassName class is:
public static ClassName get(String packageName, String simpleName, String... simpleNames)
So we could use it with empty string for the package name since you did not specify any package name in your interface spec. It will work because ClassName extends TypeName.
On the other hand we can obtain the interface's simple name using the type spec's name property.
Here a complete sample implementation. I modified the name of the variables (the variable name if that you used for the interface spec will not work as it is a java keyword).
#Data
public class SimpleClassSpecs {
public final TypeSpec interfaceSpec;
public final TypeSpec classSpec;
public SimpleClassSpecs() {
interfaceSpec = TypeSpec.interfaceBuilder("MyInterface")
.build();
TypeName interfaceTypeName = ClassName.get("", interfaceSpec.name);
classSpec = TypeSpec.classBuilder("MyClass")
.addSuperinterface(interfaceTypeName)
.build();
}
}
I used Lombok's #Data for the boilerplate code (getters and setters...)
Here is a corresponding test (assertion written with assertj):
#Test
public void should_generate_spec_with_superInterface() {
SimpleClassSpecs ps = new SimpleClassSpecs();
assertThat(ps.classSpec.toString()).contains("class MyClass implements MyInterface");
}
Or by simply doing doing a System.out.println(ps.classSpec), one can obtain the following result:
class MyClass implements MyInterface {
}

Mocking java objects gives class cast exceptions

I have a interface fly and a class duck which implements fly.
interface Fly {
getWingSize();
}
public class Duck implements Fly {
#Override
int getWingSize(){
return 1;
}
}
In my controller class, when I try to use the following:
Fly flyAnimal = Animal.getFlyingAnimal();
((Duck) flyAnimal).getWingSize();
It works fine, however in my junit, it gives a class cast exception. I am using powermockito.
In your code you are casting to concrete class (duck). In general, you would mock interfaces. Your test case might have mocked interface fly.
It should work fine if you replace ((duck) fly).getWingSize(); with fly.getWingSize();

ApiMethod with inheritance GAE

I would just know if inheritance is supported in Google Cloud Endpoints methods. Here is the scenario:
I have an interface :
public interface A {
public String getSomething();
}
and a class that implements that interface :
public class B implements A {
public String getSomething(){
return "hello";
}
}
In my class annotated with #Api I wold have a method like this :
#ApiMethod()
public void submitStatistic(A statistic)
Then when I generate the client library the B class is not generated but only the interface A is transformed in a class that is available to client side. Is there something to force in some way the transformation of class B ? and also to maintain the inheritance between this classes ?
Thank you for reading.
Yes you can:
https://developers.google.com/appengine/docs/java/datastore/jdo/dataclasses#Inheritance
and
http://www.datanucleus.org/products/accessplatform/jdo/orm/inheritance.html
Looks like you may need to include a couple extra lines to get it to work over normal Java.

Categories

Resources