I have two Plugins for IntelliJ. PluginTwo depends on PluginOne, so Two is started after One. Both Plugins depends on a third Core-Module.
The Structure:
I want to access the Dummy-Class via the Context-Class in PluginTwo. The Context class is part of the Core-Module and uses a PicoContainer to provide access on the Dummy-Class. PluginOne creates a Context with the PicoContainer on startup. Now I want to access the Dummy-Class from PluginTwo via the PicoContainer.
I got this Error:
2018-09-28 14:25:19,208 [ 12588] ERROR - roject.impl.ProjectManagerImpl - PluginTwoProjectComponent@94a5de2
java.lang.LinkageError: loader constraint violation: loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) previously initiated loading for a different type with name "Context"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.intellij.util.lang.UrlClassLoader._defineClass(UrlClassLoader.java:276)
at com.intellij.util.lang.UrlClassLoader.defineClass(UrlClassLoader.java:272)
at com.intellij.util.lang.UrlClassLoader._findClass(UrlClassLoader.java:241)
at com.intellij.ide.plugins.cl.PluginClassLoader.a(PluginClassLoader.java:142)
at com.intellij.ide.plugins.cl.PluginClassLoader.a(PluginClassLoader.java:74)
at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:61)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at PluginTwoProjectComponent.projectOpened(PluginTwoProjectComponent.java:16)
...
The PicoContainer is createt in the Context-Class:
private static Context instance;
private final MutablePicoContainer picoContainer;
public static synchronized Context getInstance() {
if (instance == null) {
instance = new Context();
}
return instance;
}
public Context() {
picoContainer = new DefaultPicoContainer();
picoContainer.addComponent(DummyClass.class);
}
public <T> T getComponent(Class<T> clazz) {
return picoContainer.getComponent(clazz);
}
The PluginOneProjectComponent get an instance of the Context
public class PluginOneProjectComponent implements ProjectComponent {
private static Context context;
private Project project;
public PluginOneProjectComponent(Project project) {
this.project = project;
}
@Override
public void projectOpened() {
System.out.println("PluginOneProjectComponent started with project " + project.getName());
context = Context.getInstance();
DummyClass dummy = context.getComponent(DummyClass.class);
System.out.println("DummyText from PluginOne " + dummy.getText());
System.out.println("DummyNumber from PluginOne " + dummy.getNumber());
}
public static Context getContext() {
return context;
}
}
From the PluginTwo I want to use the Context from PluginOne to access the DummyClass. But this don't work.
public class PluginTwoProjectComponent implements ProjectComponent {
Project project;
public PluginTwoProjectComponent(Project project) {
this.project = project;
}
@Override
public void projectOpened() {
System.out.println("PluginTwoProjectComponent started with project " + project.getName());
Context context = PluginOneProjectComponent.getContext();
DummyClass dummy = context.getComponent(DummyClass.class);
System.out.println("DummyText from Plugin Two" + dummy.getText());
System.out.println("DummyNumber from Plugin Two" + dummy.getNumber());
}
}
So the output is only.
PluginOneProjectComponent started with project HelloWorld
DummyText from PluginOne Some Text
DummyNumber from PluginOne 42
PluginTwoProjectComponent started with project HelloWorld
When i call getComponent(DummyClass.class) on the context in the debugger i only get null as result.
Can someone help me? Is there a better way to access my Context-Class from an PluginOne?
I reproduced the error in this small project to share it with you. I only need the PicoContainer from PluginOne to use it in PluginTwo. The complete source is available here: https://github.com/jafey/intellij-plugin-picocontainer-poc
As I understand you should rely on Services concept to communicate between plugins, since they're loaded in separate classloaders the type X in the first plugin is not really the same as type X in second plugin.
Also the concept of pico context meant to be private to the plugin