Using project and application services inside actions

Hi,

I found out that I don't need to call the service manager directly to get a specific service. Instead of calling ServiceManager.getService(project, MyService.class) I just specify the service as an argument in the constructor of the class that needs that service. Since IDEA creates the used instance of that class using a PicoContainer the dependency is filled in automatically. That enables me to write JUnit tests that mock those other services such as the ActionManager, the Application and my own other services away.

My plugin uses hand coded action groups that I wanted to replace with action groups defined in my plugin.xml. The problem is now: Actions registered in the plugin.xml need no-args-constructors. That's a bit weird. Why aren't those actions also created by the PicoContainer?

Well, there is a way around this problem: Register all actions and the containing action groups as project services, but that's a bit strange since there is a separate mechanism for registering actions.

Cheers,
Robert

5 comments

Hello Robert,

I found out that I don't need to call the service manager directly to
get a specific service. Instead of calling
ServiceManager.getService(project, MyService.class) I just specify the
service as an argument in the constructor of the class that needs that
service. Since IDEA creates the used instance of that class using a
PicoContainer the dependency is filled in automatically. That enables
me to write JUnit tests that mock those other services such as the
ActionManager, the Application and my own other services away.

My plugin uses hand coded action groups that I wanted to replace with
action groups defined in my plugin.xml. The problem is now: Actions
registered in the plugin.xml need no-args-constructors. That's a bit
weird. Why aren't those actions also created by the PicoContainer?


Really the main reason is most of the action management code was written
before we got a PicoContainer. :) Feel free to file a JIRA request to have
actions instantiated through PicoContainer as well.

--
Dmitry Jemerov
Software Developer
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0

Hi Dmitry,

I feared it would be an architectural necessity that actions are created outside of PicoContainers. I filled a feature request fot it now ( http://jetbrains.net/jira/browse/IDEA-12582 ).

Cheers,
Robert

0

Robert,

It's quite simple to instantiate actions in application context. What's
harder is to create some sort of ActionHandler, which can also ask for
project/module/file deps:

---
public PrintFileHandler(PsiFile file) {
}
---

instead of DataContext, and let IDEA check deps automatically and
enable/disable the handler.

0

Hi,

I think even cooler would be something like


The action would only be activated if a PsiClass object can be delivered. I don't think that passing a Psi-Object in the constructor would be good, since the active Psi-Objects change very often. So the selection of Psi-Objects available while constructing an action and at the time of performing it will most likely be different.

Cheers,
Robert

0

Hello Robert,

I think even cooler would be something like

 public class MyAction extends AnAction
> {
> public void actionPerformed(AnActionEvent event, PsiClass clazz)
> {
> ....
> }
> }
> ]]>


The action would only be activated if a PsiClass object can be
delivered. I don't think that passing a Psi-Object in the constructor
would be good, since the active Psi-Objects change very often. So the
selection of Psi-Objects available while constructing an action and at
the time of performing it will most likely be different.


This isn't really a good idea because there may be different DataConstants
(DataKeys in Selena) which return data of the same type, and guessing which
one should be used is not obvious.

--
Dmitry Jemerov
Software Developer
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0

Please sign in to leave a comment.