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)
Related
I have an interface defined as follows:
public interface Cache {
}
Then an abstract class implementing the above:
public abstract class AbstractCache implements Cache {
}
Then a concrete class inheriting from above:
public class RealTimeCache extends AbstractCache {
}
Then another class defined as follows:
public class CacheProbe {
public static <T> T probe(T base) {
return (T) Proxy.newProxyInstance(
base.getClass().getClassLoader(),
new Class[]{Cache.class},
new MethodCountInvocationHandler(base) // I am not mentioning this class as it's irrelevant
);
}
}
I have a class as follows which is using all of the above:
public class CacheLoader<T extends Cache> {
public T load() {
T result = getResult(...);
CacheProbe x = new CacheProbe(result);
return x.probe();
}
}
Lastly, the lines causing the issue (located outside above classes):
final CacheLoader<RealTimeCache> cacheLoader = getNewLoader(); //Method of this method is irrelevant and unchangeable
RealTimeCache x = cacheLoader.load(); //This is the line which is causing a runtime issue
Problem is, at run time the following exception is thrown at the last line mentioned above:
java.lang.ClassCastException: com.sun.proxy.$Proxy57 cannot be cast to RealTimeCache
However I don't see how this is possible because the dynamic proxy class generated is based on Cache.
How do I fix this ?
Please note that I can only change CacheProbe class in order to fix this. Cache, AbstractCache, RealTimeCache, CacheLoader and those last two lines are unchangeable.
However I don't see how this is possible because the dynamic proxy class generated is based on Cache.
Yes, the docs for java.lang.reflect.Proxy say
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
(emphasis added)
Thus, you cannot use Proxy to create (an instance of) a subclass of an arbitrary class of your choice.
How do I fix this ?
You can create an ordinary subclass of RealTimeCache, and return an instance of that. Proxy is meant primarily to serve for interfaces that are not known until runtime, and in that case the only way to interact with them anyway is the interface type. That's not your scenario.
If necessary, you can implement such a subclass in terms of a MethodCountInvocationHandler, just as your proxy class uses, but I'm sure it would be easier to implement whatever tooling that is supposed to provide directly.
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.
I have an interface I with method m and two concrete implementations A and B.
public interface I{
public void m();
}
public class A implements I{
public void m(){
//
}
}
public class B implements I{
public void m(){
//
}
}
I want to know when I inject I which of the two methods will be executed
#EJB
private I service;
///
service.m();
/////
None of them, it will become into an error since the application server doesn't know which implementation to use. To avoid this, just provide the id of the class implementation, which by default is the same name of the class but starting with lower case:
//uncomment one of these
//#EJB(name="a")
//#EJB(name="b")
private I service;
None of them. The code will compile, but you won't be able to deploy it on your application server. Without specifing type of injected class, you will get an Exception similar to this:
org.jboss.weld.exceptions.DeploymentException:WELD-001409 Ambiguous dependencies
for type [...] with qualifiers [...] at injection point [...]. Possible dependencies
[...] with qualifiers [...], Managed Bean [...] with qualifiers [...]
Container (i.e. your application server) won't be able to recognize which field do you really want to inject (A or B). It cannot just guess it out of thin air. To avoid this kind of errors, provide it with annotation (called qualifier) specifying whether you want to inject class A or class B. If you want an example, you should see this article.
when i run that time,this error will be produced.
500 Could not instantiate bean class
[org.broadleafcommerce.core.catalog.service.CatalogService]: Specified
class is an interface
Somewhere, you are doing a
new CatalogService();
Since it is an interface, you can create objects out of it but of some class that implements that interface. You can do:
public class MyCatalogService implements CatalogService {
...
}
and
CatalogService cs = new MyCatalogService();
Read a little more about Java classes, interfaces and inheritance. Ah, and this question was easy; but if you want answers you will probably need to add more detail to your questions.
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