I trying ModuleLayer
with JDK 11, I have created two modules Implementation
and Model
. Consider the Implementation
module provides a method which returns an object which is of type Foo
, the class Foo
is defined in Model
module.
So module Implementation
requires Model;
and module Model
exports all its namespaces.
I a separate application, I am creating Configuration
to resolve both the modules and created ModuleLayer
as well. By using layer.findLoader("Implementation").loadClass()
I have loaded a class from Implementation
module and invoked static method using method.invoke(null, "test");
which returns an Object
.
Now I don't understand, how should I can cast this object to Foo
? I cannot use (Foo) obj
because the jar of Model
module is not on classpath. and even if I put it I end up with exception
Caused by: java.lang.ClassCastException: class com.test.model.Foo cannot be cast to class com.test.model.Foo (com.test.model.Foo is in module Model of loader jdk.internal.loader.Loader @e9b78b0; com.test.model.Foo is in unnamed module of loader com.company.container.internal.Interpreters$ClassLoaders$$anon$1 @45815ffc)
Object provider=null;
try
{
var path = Path.of(Core.getConfiguration().getBasePath().getPath() ,"\\model\\lib\\EC");
ModuleFinder finder = ModuleFinder.of(path);
var parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("Implementation"));
ClassLoader scl = this.getClass().getClassLoader(); // intentionally using this class's loader
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
var cl = layer.findLoader("Implementation");
Class<?> classTest = cl.loadClass("com.test.AutoConfiguration");
var method = classSendMailFromX.getMethod("getProvider", String.class);
provider = method.invoke(null, "test");
}
catch (Exception e) {
throw new CoreException(e);
}
if(provider == null)
{
throw new Exception("provider cannot be empty");
}
var myProvider = (Foo) provider; // This line compiles but calls fails at runtime if I put `Model` module jar on classpath
I understand the reason, that any jar (even if it is a module) at classpath will be treated as unnamed module. But, why I cannot able to cast it? And is there any way to do it?
Foo
throughInterpreters$ClassLoaders$$anon$1@45815ffc
and another classFoo
throughLoader@e9b78b0
, these are different classes. Whether theseFoo
classes belong to a module, doesn’t matter. – Boloney