PersistentStateComponent saves state only in session Follow
Answered
Hi,
I need PersistentStateComponent to save user preferences. The component works fine only while in session, but when I close and open IntelliJ the values do not persist. It seems that the issue is that the state is not saved into a file. Adding full code:
```
@State(
name = "ConfigProviderState",
storages = {
@Storage(value = "$APP_CONFIG$/configProvider.xml")
}
)
public class ConfigProvider implements ApplicationComponent, PersistentStateComponent<ConfigProvider.State> {
@NotNull
@Override
public String getComponentName() {
return getClass().getSimpleName();
}
@Override
public void disposeComponent() {}
@Override
public void initComponent() {}
public State state = new State();
public static class State {
public State() {}
public String foo;
}
@Override
@org.jetbrains.annotations.Nullable
public ConfigProvider.State getState() {
return state; //Saves all public variables to disk.
}
@Override
public void loadState(ConfigProvider.State state) {
XmlSerializerUtil.copyBean(state, this);
}
public String getFoo() {
if (this.state.foo == null) {
this.state.foo = "test";
}
return this.state.foo;
}
public void setFoo(String foo) {
this.state.foo = foo;
}
}
Plugin XML:
<extensions>
<applicationService
serviceImplementation="com.demisto.plugin.ide.ConfigProvider"
serviceInterface="com.demisto.plugin.ide.ConfigProvider"
/>
</extensions>
<application-components>
<component>
<implementation-class>com.plugin.ide.ConfigProvider</implementation-class>
<interface-class>com.plugin.ide.ConfigProvider</interface-class>
</component>
</application-components>
Calls to the component:
ConfigProvider c = ServiceManager.getService(ConfigProvider.class);
c.setFoo(value);
ConfigProvider c = ServiceManager.getService(ConfigProvider.class);
return c.getFoo();
Would highly appreciate your help here.
Thank you,
Shachar
Please sign in to leave a comment.
Probably, caused by using same class both as service and component.
You might want to remove "<applicationService ... />" registration from plugin.xml and use `ApplicationManager.getApplication().getComponent(ConfigProvider.class)` instead of `ServiceManager.getService(ConfigProvider.class)`.
Also, you can omit explicit `<interface-class ... />` if it duplicates implementation class.
Implementing `ApplicationComponent` interface is also not necessary (and it is deprecated).
Hi Aleksey,
Thank you for the fast response. After your suggestions, the code works.
Now, I want to save a Map of all the user preferences (I can't predict the key values in advance), but then I experience the persistence issues again.
I guess that maybe you can't serialize a Map to the XML?
What would be the correct approach to save these values?
Thank you,
Shachar
Usually, it is possible to use Map/List/etc for serialisation. This requires some fragile runtime magic, though.
See https://github.com/JetBrains/intellij-community/blob/master/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchSettings.java as an example.
Please, share your implementation if you need a suggestion here.
If your case is tricky (ex: key/value types may differ), you can always serialize/deserialize your data manually (or with some help of com.intellij.util.xmlb.XmlSerializer).
See https://github.com/JetBrains/intellij-community/blob/master/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java#L131 as an example (just use Element as a State for PersistentStateComponent).
Hi Aleksey,
It should have only <String, String> pairs. I followed the code from - https://github.com/JetBrains/intellij-community/blob/4999f5293e4307870020f1d0d672a3d35a52f22d/plugins/git4idea/src/git4idea/config/GitVcsSettings.java#L53
But I still experience the same result (data is only persisted per session)
Attached is my full code:
Would much appreciate your help here!
Shachar
Please, check errors output.
It should have smth like "Caused by: com.intellij.configurationStore.UnknownMacroException: Unknown macro: $WORKSPACE_FILE$ in storage file spec: $WORKSPACE_FILE$" in it.
You're registering application component, but are trying to use Project-specific macro for "workspace.xml".
Replace "StoragePathMacros.WORKSPACE_FILE" with "some_config.xml" or use project component instead.
Thank Aleksey! Works beautifully. For the next time - where should I see this errors output? I didn't see any errors through notifications
In IDE log file (Help | Show Log in <system file manager>) or in "Console"/"idea.log" tabs in Run/Debug toolwindow.