Closed paulsen-it closed 7 months ago
@paulsen-it your components should implement Plugin interface , is that the case?
Yes, MyInterface extends Plugin
And of Course PluginC
can you try autowiring spring's
ObjectProvider<MyInterface>
instead of List<MyInterface>
I will try it out and report back
Sorry it took so long. I had to do a few other things before I could test this.
Now I have tried it. I get now 7 results. Unfortunately they are all hidden as proxy and stream. Here is a debug excerpt:
Name: com.wizzdi.flexicore.boot.base.init.FlexiCoreDependencyObjectProvider
Number: 7
InProxy: jdk.proxy10.$Proxy516
Unproxy: java.util.stream.ReferencePipeline$2
test: de.xyz.ClassA1
InProxy: jdk.proxy4.$Proxy382
Unproxy: java.util.stream.ReferencePipeline$2
InProxy: jdk.proxy5.$Proxy383
Unproxy: java.util.stream.ReferencePipeline$2
InProxy: jdk.proxy6.$Proxy384
Unproxy: java.util.stream.ReferencePipeline$2
InProxy: jdk.proxy7.$Proxy385
Unproxy: java.util.stream.ReferencePipeline$2
InProxy: jdk.proxy8.$Proxy381
Unproxy: java.util.stream.ReferencePipeline$2
InProxy: jdk.proxy9.$Proxy472
Unproxy: java.util.stream.ReferencePipeline$2
test: de.xyz.ClassB1
Both plugins now seem to be installed.
Unfortunately, I have not yet been able to find out what the other objects are.
I have now got it solved so that it runs with as well as without proxy. But it is a bit strange. Is there a simpler solution?
for (MyInterface myInterface : this.foundPlugins.stream().toList()) {
// Unproxy
if (AopUtils.isAopProxy(myInterface) && myInterface instanceof Advised) {
Object target = ((Advised) myInterface).getTargetSource().getTarget();
// Unstreaming
if (target instanceof Stream<?>) {
List<?> myInterfaceObjList = ((Stream<?>) target).toList();
for (Object myInterfaceObj : myInterfaceObjList) {
this.pluginList.add((MyInterface) myInterfaceObj);
}
}
} else {
this.pluginList = this.foundPlugins.stream().toList();
}
}
can you attach the full code please?
@Service
@ComponentScan("framework.plugin")
@Extension
@Getter
public class PluginC implements Plugin {
@Autowired(required = false)
@Lazy
private ObjectProvider<MyInterface> foundPlugins;
private List<MyInterface> pluginList = new ArrayList<>();
@PostConstruct
public void init() {
for (MyInterface myInterface : this.foundPlugins.stream().toList()) {
// Unproxy
if (AopUtils.isAopProxy(myInterface) && myInterface instanceof Advised) {
Object target = ((Advised) myInterface).getTargetSource().getTarget();
// Unstreaming
if (target instanceof Stream<?>) {
List<?> myInterfaceObjList = ((Stream<?>) target).toList();
for (Object myInterfaceObj : myInterfaceObjList) {
this.pluginList.add((MyInterface) myInterfaceObj);
}
}
} else {
this.pluginList = this.foundPlugins.stream().toList();
}
}
LOG.debug("Found Classes:");
if (pluginList != null) {
for (MyInterface plugin : pluginList) {
LOG.debug(plugin.getClass()
.getName());
}
}
LOG.debug("----------");
}
}
please try these two things:
instead of printing the classes which will be subjected to proxying (proxying is a normal thing) simply try to call this.foundPlugins.stream().foEach(f->f.myFunction()) but if i recall correctly there shouldnt be any issue with calling getClass() aswell.
also there is probably no reason to keep a list of found plugins , you could just use foundPlugins directly.
If I use foundPlugins directly I get 7 proxy objects. Most of them are completely empty. To have only my plugins, I use the PostConstruct and filter out the empty objects.
can you construct a minimal example repository and provide a link to it ?
It works with the simple workaround. It is Ok for me. You can close the Issue.
Hello Asaf,
so far everything has gone great with FlexiCore. But now I have a problem again. I have 3 plugins.
Plugin A
with two classesPlugin B
with a classPlugin C
where the plugins A and B are to be autowired in a listAt the end, plugin C should contain 3 entries in the list "
pluginList
".ClassA1, ClassA2, ClassB1
Unfortunately, only the classes from the plugin that is loaded last are entered in the list. The ones from the first plugin are not in the list. Although they are loaded. The constructor is called and the init() method is also executed, but always shows only the currently loaded plugin. As if the list is always completely overwritten. I have also changed the setter, but unfortunately this does not help.If I change the order in which the plugins are loaded. E.g. by renaming them. Then the classes are entered in the list from the last plugin. So it really seems to be the loading order.