UnsatisfiableDependenciesException when loading ProjectComponent in Irida
Hi, I've never written a ProjectComponent before. I'm using Irida. I define my ProjectComponent implementation-class correctly in my <project-components> element, and my class has the constructor:
This seems to be correct, but when I load my plugin in an Irida plugin sandbox, I get this exception:
Does anyone know why this would happen, or how to fix it?
Thanks,
-Keith
Please sign in to leave a comment.
It seems you've declared it to be an application component. Can you post
your plugin.xml here?
Keith Lea wrote:
Here is my plugin.xml:
Nully Checker 0.1 Keith Lea net.kano.nully.NullyProjectComponent ]]>
Keith,
That's really strange, but I've got problems in unscrambling your
stacktrace both in 75 & 84 builds. Which builds are you using? Can
someone give stacktrace too?
I'm using the latest, 3084. I've attached my plugin sources.
Attachment(s):
nully.zip
For what it's worth, I had this problem as well, and it seems to be gone in 3089.
--Dave Griffith
Whoops, I was wrong. Still getting the error.
It still happens to me too, in 3089 the error is:
org.picocontainer.defaults.UnsatisfiableDependenciesException: net.kano.nully.NullyProjectComponent doesn't have any satisfiable constructors. Unsatisfiable dependencies: [[interface com.intellij.openapi.project.Project]]
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getGreediestSatisifableConstructor(ConstructorInjectionComponentAdapter.java:138)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.instantiateComponent(ConstructorInjectionComponentAdapter.java:193)
at org.picocontainer.defaults.InstantiatingComponentAdapter.getComponentInstance(InstantiatingComponentAdapter.java:48)
at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:42)
at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:37)
at org.picocontainer.defaults.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:298)
at com.intellij.openapi.components.impl.ComponentManagerImpl.instantiateComponent(ComponentManagerImpl.java:156)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:158)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponentFromContainer(ComponentManagerImpl.java:84)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponent(ComponentManagerImpl.java:137)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponent(ComponentManagerImpl.java:142)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponents(ComponentManagerImpl.java:159)
at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java:111)
at com.intellij.openapi.project.impl.BaseFileConfigurable.init(BaseFileConfigurable.java:130)
at com.intellij.openapi.project.impl.d.init(d.java:111)
at com.intellij.openapi.project.impl.ProjectManagerImpl.newProject(ProjectManagerImpl.java:178)
at com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl.initComponent(FileDocumentManagerImpl.java:235)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:24)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponentFromContainer(ComponentManagerImpl.java:201)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponent(ComponentManagerImpl.java:137)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponent(ComponentManagerImpl.java:142)
at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponents(ComponentManagerImpl.java:159)
at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java:111)
at com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:32)
at com.intellij.idea.d.c(d.java:3)
at com.intellij.idea.Main$2.run(Main$2.java)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:454)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)
I get the same here, but preceeded by this exception:
java.lang.ClassCastException
at
com.intellij.openapi.components.impl.ComponentManagerImpl.instantiateComponent(ComponentManagerImpl.java:156)
at
com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:158)
at
com.intellij.openapi.components.impl.ComponentManagerImpl.b(ComponentManagerImpl.java:202)
at
com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java:255)
at
com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:32)
at com.intellij.idea.d.c(d.java:3)
at com.intellij.idea.Main$2.run(Main$2.java)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:454)
at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)
Keith Lea wrote:
Keith Lea wrote:
Seems very much the same problem Alain expected with AnAction class.
Don't you added openapi.jar manually to the module classpath? You
shouldn't to that cause plugin module automatically gets necessary
libraries from the specified sandbox. Please make sure the deployed
plugin doesn't have openapi.jar in lib folder. If it is indeed so you
need to remove openapi.jar from the Path's dialog and from deployed
sandbox manually (the latter is devkit lib sync bug, to be fixed).
--
Maxim Shafirov
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
It looks like this fixed the problem. Thanks.
I have another question related to my project: is it possible to view the transformed source files which were transformed with JavaSourceTransformingCompiler?
Additionally, how am I supposed to modify the files during transform? It says I need to use a read / write action, but these files aren't being edited by the user, so I should be able to read and write freely, don't you think? Okay, so if I can't, my ProjectComponent adds my transforming compiler to the project, but then to run a write action, my compiler needs an instance of Application, but how does a ProjectComponent get this?
Yup, this did it for me as well. BTW, thanks for all of this. The UI for plugin development is still pretty raw, but it's so worth it to actually be able to debug IPP and IG using a debugger, rather than System.out.println.
--Dave Griffith
Max, do you have a solution for my situation:
My plugin consists of several modules, some java modules and one plugin module. The plugin module gets the openapi library automatically from the sandbox, but the java modules don't. Therefore I have to add the openapi library manually to the classpath of the java modules, leading to the known problem.
I tried to export the sandbox libraries from the plugin module and make the java modules depend on the plugin module (leading to a circulary dependency), but it didn't work.
An even worse case is another plugin which has to work with different IDEA versions. There I have a plugin module containing only some base component and for each IDEA version a separate java module with the correct openapi library for this IDEA version. As long as I delete the openapi library manually after building everything works fine. (Thanks to the devkit lib sync bug I don't have to delete it over and over again...)
Hello Martin,
Same problem here. I would love to hear from JB about this.
Jacques
Jacques Morel wrote:
>>My plugin consists of several modules, some java modules and one
>>plugin module. The plugin module gets the openapi library
>>automatically from the sandbox, but the java modules don't. Therefore
>>I have to add the openapi library manually to the classpath of the
>>java modules, leading to the known problem.
Have no idea right now. Need to think about a bit.
--
Maxim Shafirov
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
Is there a possibility to use the 'export' flag, i.e. only those libraries marked to be exported are copied over? Since the library will get copied into the common lib directory it shouldn't hurt to export it to other modules.
Martin Fuhrer wrote:
>>Have no idea right now. Need to think about a bit.
We have better idea IMO. What if the openapi will be included in
configured JDK rather than a separate library. The same pattern now
works for J2ME modules. From the user perspective the only noticable
change would be moving sandbox config to JDK configuration.
--
Maxim Shafirov
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
It's not possible to view transformations made by compiler unless you explicitly open it in the editor. The main idea behind this
kind of compiler is to make transformations transparent to the end-user.
You can modify them in any way, however there are 2 issues:
1. If you use VirtualFile for modifications reading it should be done either in a SwingThread or in a ReadAction. If you modify the
file, this should be done in SwingThread and inside a WriteAction (this requirement is global for all IDEA components)
2. You can obtain a path from the VirtualFile (ReadAction required) and write your transformation code in terms of java.io.File,
then you won't need any WriteActions.
The Application instance is obtained as following:
ApplicationManager.getApplication();
--
Best regards,
Eugene Zhuravlev
Software Developer
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
That would mean I have to configure a whole JDK for each IDEA version - somewhat overkill, but possible. (At least better than using the export flag.)
What about a special kind of global library? Then the library wouldn't be directly related to the JDK.
Whatever you'll do, just support my setup:
module1 (common) -> libraries from whatever version
module2 (idea 4.0) -> libraries from IDEA 4.0
module3 (idea 4.5) -> libraries from IDEA 4.5
module4 (idea 5.0) -> libraries from IDEA 5.0
module5 (plugin) -> libraries from whatever version
All modules are using the same JDK, module1 and module5 are using only classes which are identical for all versions (e.g. ApplicationComponent).
Martin Fuhrer wrote:
>>Martin Fuhrer wrote:
>>
>>>>Have no idea right now. Need to think about a bit.
>>>
>>>
>>>Is there a possibility to use the 'export' flag,
>>
>>i.e. only those libraries marked to be exported are
>>copied over? Since the library will get copied into
>>the common lib directory it shouldn't hurt to export
>>it to other modules.
>>We have better idea IMO. What if the openapi will be
>>included in
>>configured JDK rather than a separate library. The
>>same pattern now
>>works for J2ME modules. From the user perspective the
>>only noticable
>>change would be moving sandbox config to JDK
>>configuration.
In other words let users configure libraries themselves. The whole point
of devkit was to make to process more transparent.
--
Maxim Shafirov
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
Don't be disappointed... :)
First of all devkit is (at least for me) far more than simply configuring libraries. It's an invaluable tool to set up the plugin structure automatically (create plugin.xml, place it to the correct location, copy class files from different modules to the correct location, etc.) and to launch a test instance of IDEA in a very easy way. Already now devkit makes my life a lot easier.
Now for the library configuration:
There's another approach: add another option to the plugin module type, indicating if it is a real plugin (with a plugin.xml) or just a 'library module'. Then I can create a sandbox configuration for each IDEA version (as soon as you are also looking for openapi.jar in lib/dev) and create all my modules as plugin modules by attaching the correct sandbox. And in one of the modules (module5 in my example above) I set the 'real plugin' flag and get the plugin.xml for it.
What do you think about that?
>Already now devkit makes my life a lot easier.
Strongly agree, now that I've fought my way through the configuration for my plugins. Previously, testing new plugin functionality meant deploying it into my configuration, stopping and restarting IDEA, and hoping I hadn't screwed up anything so badly that I would have to clean it out and start over. Now, I can test just by clicking the "Run" button. Next step is to try debugging, which will rule (it was always so much hassle previously to set up debugging on a plugin that I just used System.out.println). Wish I'd had this about 350 inspections ago...
You will love it. No more restarting IDEA after changing code, just compiling and hotswapping...
(But by the way, that's not new with devkit. I always had two instances of IDEA 4.5, one for development and the other in debug mode. The output paths of my plugin projects pointed to the plugin folder of the second instance, debugger attached remotely through shared memory, and debugging was quote smooth.)
It's very un-intuitive to have to wrap my code in a WriteAction, within an invokeAndWait. I think JavaSourceTransformingCompiler should be automatically executed within event dispatch thread, and within write action. After all, every java source transforming compiler will want to write to the files.
I asked if I could view transformations just for debugging. I think this might be a nice enhancement for:
1. debugging, so I can make sure the right code is being generated
2. for the end-user, so they can see what's going on underneath, possibly to spot a bug
Another question, from JavaSourceTransformingCompiler, how am I supposed to get the Project instance from the (CompileContext context, VirtualFile file) which is passed to transform()? It looks like I can't call getModuleForFile(file), probably because the file is not in the project, it is temporary. My current solution is this:
But that's sort of messy. Is that the recommended way?
I have another problem, from within my JavaSourceTransformingCompiler, I'm calling:
This PsiFile is not a Java PSI File, it's a plaintext file. How can I load it as a Java PSI File?
Guys,
Maybe I am dense but what if
1. all modules that are part of a plugin are plugin modules
2. in the plugin run config you only specify the top level module (the one with plugin.xml). IDEA would follow the dependencies to deploy the others.
Wouldn't this work?
This is what intuitively I did when setting up my multi-module plugin. My reasoning was that even my common module depends on IDEA OpenAPI and is as much a plugin as my other top level module. The only difference is that the common module doesn't have a plugin.xml
When creating a new module, at the page where IDEA asks what sandbox to use, it could also ask if this module would be a top level module and should have its plugin.xml created.
The other case we did not talk about is when a plugin depends on another. It would be nice if both could be deployed at the same time.
Jacques
That matches almost exactly what I proposed above. Would be quite satisfying to me.
About the inter-plugin dependencies:
AFAIK DevKit doesn't delete the content of the sandbox when deploying a module. So you can deploy the first module and then the second one which depends on the first. Only problem here is that the plugin is deployed whith it's module name. In my case there are several plugins (in different projects) with all of them having a module called 'plugin'. So when deploying the second plugin it overwrites the first one. I think it would be better to specify a deployment name in DevKit, matching the name with which the plugin will be deployed at the end. In a further step this setting could be used to automatically create a uploadable jar or zip file.
>
It's a common requirement, not only of Compiler subsystem. You may want to do transformations not via VirtualFiles and thus you
won't need the WriteAction, so it is left for the compiler instance to decide.
>
For debugging you may stop at a breakpoint in debugger and examine the code that is produced.
All transforming compilers are supposed to be a project components, so just declare your compiler's constructor as having a Project
parameter. The project instance will be passed to it on project initialization. The recommended way is to use the saved instance of
the Project.
--
Best regards,
Eugene Zhuravlev
Software Developer
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
Currently you cannot, since the file is located outside the project
In order to enable such a trick I've added additional parameter "originalFile" for which you can obtain a valid PsiJavaFile. Please
read updated javadocs carefully when the build with this change is available (build number > 3111)
--
Best regards,
Eugene Zhuravlev
Software Developer
JetBrains Inc.
http://www.jetbrains.com
"Develop with pleasure!"
"Keith Lea" <keith@cs.oswego.edu> wrote in message news:2011005.1100899013260.JavaMail.itn@is.intellij.net...
>I have another problem, from within my JavaSourceTransformingCompiler, I'm calling:
This PsiFile is not a Java PSI File, it's a plaintext file. How can I load
This would help, but how would I use it to modify the temporary file through the PSI? I need to be able to modify the PSI tree during the transformation (it would be too tedious to make the changes myself).
Also, getting a PSI tree for an arbitrary file sounds like a reasonable request for OpenAPI, should I file an SCR?