persisting a run/debug configuration
Hi,
I am trying to persist the run/debug configurations created by my plugin. I have mainly looked at the JUnit and TestNG plugins as examples.
My configuration object extends ModuleBasedConfiguration, which if I go up the inheritance tree implements JDOMExternalizable. The plugins I looked as examples implement public void readExternal(Element element) and public void writeExternal(Element element) from this interface, where they seem to read/write their data. So I created some basic implementation for this that I copied from these plugins. I put in some prints to trace it, and these methods do get called and it does not crash (whee!). I have idea though if the data is written/read properly back in or not as I see nothing about it.
So, when I create a new run/debug configuration of my type, it gets listed in the run configurations. It also persists if I close the IDE and restart it. But all the data in it seems to be lost, or at least it never gets back into the configuration UI for that entry. For example, my type is called OSMO. I create an instance of type OSMO, give it a name "hello", and fill in a bunch of stuff. Click OK. close it and reopen. "hello" is still listed, but all fields are empty. My SettingsEditor implements resetEditorFrom and applyEditorTo, which fills in the data from given configuration object.
The configuration objects (for JUNit and TestNG plugins these are JUnitConfiguration.java and TestNGConfiguration.java) also have a method called protected ModuleBasedConfiguration createInstance(), which seems to be called with the name of the configuration. But what I don't see is how they map the name to some instance of loaded data? I could create a map of names to instances and try to persist through that, but I don't see the example plugins doing this so I guess there is some other way this is handled.
So, the question is just, how do I persist data for my custom run/debug configurations and read it back?
Thanks,
Teemu
请先登录再写评论。
OK, I think I got the persist thing working. Just a few notes if anyone finds a need for this some day.
The configuration definitions are stored under the ".idea" folder in the "workspace.xml" file. You can check from there what gets stored and what not.
Using the legacy JDOMExternalizer I copied from JUnit/TestNG plugins did not work for me. Nothing was getting stored/loaded. There was a different example in the Maven plugin using the newer API. This is what I found works for me:
@Override
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
//this is the tag name that the XmlSerializer.serialize produces
String name = OSMORunParameters.class.getSimpleName();
Element settingsElement = element.getChild(name);
//if it is in wrong format (e.g., old with different class or tag name, or missing data from experiments), missing this check will produce a nullpointer and user loses all run definitions
if (settingsElement == null) return;
//not sure if you can create a new instance or not but just to be sure I don't
runParameters.setFrom(XmlSerializer.deserialize(settingsElement, OSMORunParameters.class));
readModule(element);
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
super.writeExternal(element);
//the tag name in the XML file will be the class name of runParameters
element.addContent(XmlSerializer.serialize(runParameters));
//this writes the name of chosen module
writeModule(element);
}
I guess IDEA still internally uses the JDOM thing as the method names match that, but this attaches to the same XML tree and works. The Maven plugin defines a static field called TAG but it needs to be the exact same as the class name so that can be a bit confusing. Anyway, just using the class name as above it worked for me.
As a final note, if the configuration data (OSMORunParameters here) contains anything but primitive types or Map instance (maybe Collections?), it just ignores those. So I have to change my more complex configuration into maps I guess. But as long as it works..
And how do the objects get created? I have no idea but hey, it works now.. or so I think :)
Teemu
Perhaps this will help?
You implement an exetnsion point so that the platform knows about you.
Here are 3 you should look at:
<configurationType id="Lua" implementation="com.sylvanaar.idea.Lua.run.LuaConfigurationType"/>
<configurationProducer id="Lua" implementation="com.sylvanaar.idea.Lua.run.LuaRunConfigurationProducer"/>
<programRunner implementation="com.sylvanaar.idea.Lua.run.LuaRunner"/>
They register a "Type" of configuration, create instances of it, and then run those instances.
Here are my Lua run configurations. I borrowed code where I could and just worked through the rest myself.
https://bitbucket.org/sylvanaar2/lua-for-idea/src/e3fa28b0b04a2da6816b019464340a10aa7b24ff/src/run?at=idea12
There most of the code.
@Jon Akhtar - So you just need those 3 extension points to handle persisting/reading Run Configurations? Which piece does the persisting/reading when Apply/OK is clicked in the Edit Run Configuration UI? I have a Type and a ProgramRunner, but no values are persisted upon clicking Apply/OK, and then obviously, user-defined values are not read back in my code or when I edit the Run Configuration in the UI.
Also, it appears your RuntimeConfigurationProducer is deprecated, and RunConfigurationProducer is preferred now.
Per @teemu kanstren it sounds like I have to make a Component to handle this (though I'm not clear what is triggered when Apply/OK is clicked, or when/how to read-back values for user in code or Edit Configuration).