Resolve "Class is not compatible with Class<T>" - java

I'm using in a Java-Project a Framework (Ashley).
To use it I often have to write something like that:
entityEngine.getSystem(RenderingSystem.class).setProcessing(true);
While RenderingSystem is something Ive created, getSystem is an Part of the Framework itselve. Viewing the implementation of that method it looks like that:
/**
* Quick {#link EntitySystem} retrieval.
*/
#SuppressWarnings("unchecked")
public <T extends EntitySystem> T getSystem(Class<T> systemType) {
return systemManager.getSystem(systemType);
}
Now, even when I can compile and run the code with gradle, my IDE (IntelliJ) shows errors with the following warning:
What did I wrong, or how can I suppress these kind of warnings at least?
EDIT
Here is the definition of my class "RenderingSystem":
public class RenderingSystem extends EntitySystem {...}

Your method accept class of type T which is T extends EntitySystem>
Your RenderingSystem have to extend EntitySystem (or implement if EntitySystem is an interface) to be compatible to that method

While RenderingSystem is something Ive created, getSystem is an Part
of the Framework itselve. Viewing the implementation of that method it
looks like that:
If you pass a RenderingSystem class you defined in your own project and that you cannot pass it to the getSystem() methods, it means that RenderingSystem doesn't derive from EntitySystem.
You should probably extend/implement the EntitySystem class of the framework to make the getSystem() method usable with your own classes passed as parameter.

Related

Gradle Cannot have abstract method

I'm developing a custom binary Gradle plugin, following the pattern shown here.
My extension, VersionInfoExtension is abstract with abstract methods, just like the BinaryRepositoryExtension in the documentation. My task is also abstract, with abstract methods for the parameters, like the LatestArtifactVersion in the documentation. When I test, I get the following error:
An exception occurred applying plugin request [id: 'com.example.version-info']
> Failed to apply plugin 'com.example.version-info'.
> Could not create an instance of type com.example.gradle.version.VersionInfoExtension.
> Could not generate a decorated class for type VersionInfoExtension.
> Cannot have abstract method VersionInfoExtension.jars().
What am I missing? Are there any good examples of making this work?
I'm using gradle 7.X and Kotlin.
The "Cannot have abstract method myPropertyName" error is reported when the method name is prefixed by "is":
abstract val isRegistered: Property<Boolean>
That was annoying to track down. The type doesn't seem to matter.
The solution was to remove "is" from the name.
The problem here seems to be the name of the abstract method.
All configurable methods must be bean-methods - this holds for both Extensions and Tasks.
So you should have used (assuming a java class):
abstract Property<String> getJars()
instead of
abstract Property<String> jars()
In addition to #Richard Sitze answer, in my case it was a custom setter function that was used in tests only (annotated with #TestOnly) was preventing generating the class.
I had declared serializable object as #Input
#get:Input
abstract val myPropertry : Property<MyObject>
#Test
fun setMyProperty(obj : MyObject){
//...
}
Somehow the name of the function interfered with generating the property setter along generation of the setter.

How to handle package name changes in Java, if both versions need to be supported?

I need to support two versions of a dependency, which have the same API but different package names.
How do I handle this without maintaining two versions of my code, with the only change being the import statement?
For local variables, I guess I could use reflection (ugly!), but I use the classes in question as method argument. If I don't want to pass around Object instances, what else can I do to abstract from the package name?
Is it maybe possible to apply a self-made interface - which is compatible to the API - to existing instances and pass them around as instance of this interface?
I am mostly actually using xtend for my code, if that changes the answer.
Since you're using Xtend, here's a solution that makes use of Xtend's #Delegate annotation. There might be better solutions that aren't based on Xtend though and this will only work for simple APIs that only consist of interfaces with exactly the same method signatures.
So assuming you have interfaces with exactly the same method signatures in different packages, e.g. like this:
package vendor.api1
interface Greeter {
def void sayHello(String name)
}
package vendor.api2
interface Greeter {
def void sayHello(String name)
}
Then you can combine both into a single interface and only use only this combined interface in your code.
package example.api
interface Greeter extends vendor.api1.Greeter, vendor.api2.Greeter {
}
This is also possible in Java so far but you would have to write a lot boilerplate for each interface method to make it work. In Xtend you can use #Delegate instead to automatically generate everything without having to care how many methods the interface has or what they look like:
package example.internal
import example.api.Greeter
import org.eclipse.xtend.lib.annotations.Delegate
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
#FinalFieldsConstructor
class GreeterImpl implements Greeter {
#Delegate val Api delegate
}
#FinalFieldsConstructor
class Greeter1Wrapper implements Greeter {
#Delegate val vendor.api1.Greeter delegate
}
#FinalFieldsConstructor
class Greeter2Wrapper implements Greeter {
#Delegate val vendor.api2.Greeter delegate
}
Both Greeter1Wrapper and Greeter2Wrapper actually implement the interface of both packages here but since the signature is identical all methods are forwarded to the respective delegate instance. These wrappers are necessary because the delegate of GreeterImpl needs to implement the same interface as GreeterImpl (usually a single delegate would be enough if the packages were the same).
Now you can decide at run-time which version to use.
val vendor.api1.Greeter greeterApi1 = ... // get from vendor API
val vendor.api2.Greeter greeterApi2 = ... // get from vendor API
val apiWrapper = switch version {
case 1: new Greeter1Wrapper(greeterApi1)
case 2: new Greeter2Wrapper(greeterApi2)
}
val example.api.Greeter myGreeter = new GreeterImpl(apiWrapper)
myGreeter.sayHello("world")
This pattern can be repeated for all interfaces. You might be able to avoid even more boilerplate by implementing a custom active annotation processor that generates all of the required classes from a single annotation.

Bind default implementation in case of multiple implementation in Guice

I have class hierarchy as follows:
interface Pen{}
class SimplePen implements Pen{}
class ComplexPen implements Pen{}
Code using this is as follows
class A{
public A(Pen pen){}
}
class B{
public B(ComplexPen pen){}
}
So what i want to do is, by default Pen should be bound to SimplePen and ComplexPen should be bound only when asked explicitly as in case of class B.
bind(Pen.class).to(SimplePen.class).in(Singleton.class)
bind(ComplexPen.class)
The above Guice config fails at runtime saying implementation of Pen already bound. How do i go about this?
Note am trying to avoid .annotatedWith(Names.named("complexPen"))
My bad, the code i gave works. I had some extra code which was creating more bindings.
bind(Pen.class).to(SimplePen.class).in(Singleton.class)
bind(ComplexPen.class)

can't cast to implemented interface

i'm very confused...
I have a class which directly implements an interface:
public class Device implements AutocompleteResult
{...}
Here is proof that I'm looking at the right variables:
Object match = ...;
log.debug(match.getClass()); // Outputs 'Device'
log.debug(match.getClass().getInterfaces()[0]); // Outputs 'AutocompleteResult'
Yet when I try to cast an instance of the class to the interface:
AutocompleteResult result = (AutocompleteResult) match;
I get a ClassCastException!
ClassCastException: Device cannot be cast to AutocompleteResult
Also, isAssignableFrom returns false and i'm not sure why:
log.debug(AutocompleteResult.class.isAssignableFrom(Device.class));
from the doc:
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.
Shouldn't I always be able to cast a object to an interface its class implements?
Thanks.
This can happen if two different classloaders load a class named AutocompleteResult.
These two classes are then treated as entirely different classes, even if they have the same package and name (and even implementation/fields/methods).
A common cause for this is if you use some kind of plugin system and both your base classes and the plugin classes provide the same class.
To check for this issue print the value returned by Class.getClassLoader() on both offending classes (i.e. the class of the interface implemented by Device and the result of AutocompleteResult.class).
AKA when Java apparently doesn't Java.
I hit this problem recently with Play Framework 2.6.3, what helped me was this:
https://www.playframework.com/documentation/2.6.x/ThreadPools#Application-class-loader
I leave this info here for the people that might have the same problem.
To make it clearer, what helps is:
Injecting Application on an Eager Singleton and then using its classloader to load the classes I was having issues with.
To make it clearer
public class Module {
#Override
public void configure {
bind(TheClassLoaderLoader.class).asEagerSingleton()
public static class TheClassLoaderLoader {
#Inject
public TheClassLoaderLoader( Application application) {
ClassLoader classloader = application.classloader();
Class<?> interfaceClass = classloader.loadClass(InterfaceClass.class.getName());
classloader.loadClass(ImplementsInterfaceClass.class.getName()).asSubclass(interfaceClass);
The example here https://playframework.com/documentation/2.6.x/JavaDependencyInjection#Configurable-bindings
That uses Environment often throws a frustrating ClassNotFoundException
Cheers

How does Spring's #Autowired work with interfaces that have no implementation?

I am working with SpringData's Neo4j graph DB hello-worlds example and I ran across the following code in WorldRepositoriesImpl.java...
#Autowired private WorldRepository worldRepository;
Furthermore, WorldRepository is defined as...
public interface WorldRepository extends MyWorldRepository,
GraphRepository<World>,
NamedIndexRepository<World>
{/* no method defined here */}
Now the odd part, no class that I can find actually implements WorldRepository.So, a few questions...
How is this possible? Where is this documented? Is there a way to make this a bit more explicit (less mysterious)?
Running the code with a debugger attached shows that the worldRepository instance wired up by Spring is a proxy object created at runtime.
Looking at the pom.xml and the dependencies included, it looks like the spring-neo4j library bundles in some Aspects that create this implementation class at runtime.
In other words, there is no implementation of this interface declared in the source code - but one is created at runtime with AspectJ and other tools.

Categories