Module based PersistenStateComponent not saving state to .iml file

Hi,

I'm writing a plugin for IntelliJ and can't get the PersistentStateComponent interface to work correctly with my ModuleComponent. The getState() method is called, but the state won't be saved to the .iml file. Because of that, the loadState() method never is called.

I redid the whole PersistentStoreComponent thing with a new plugin. For that, only one class is defined:

 
public class StorageTestSettingsPage implements Configurable, ModuleComponent, PersistentStateComponent<Boolean>

The class simply uses a boolean value, which can be altered via a checkbox in the settings of the module.

In my plugin.xml, I declared the class implementing the PersistentStateComponent as a module-component:

 
<module-components>
    <component>
        <implementation-class>StorageTestSettingsPage</implementation-class>
    </component>
</module-components>
 

This is the annotation at the beginning of the class:

 
@State(
        name = "myName",
        storages = @Storage(id = "default", file = StoragePathMacros.MODULE_FILE)
)


The implementation of getState() and loadState():

 
@Override
public Boolean getState() {
    return value;
}

 
@Override
public void loadState(Boolean state) {
    this.value = state;
}


When I debug the call of the getState method, I can see the correct value being returned. Nonetheless, the .iml file of the module stays untouched. So the value differs from the initial value and should therefore be stored in the .iml file, as described here. Using a wrapper class for the values doesn't solve the issue.

What is wrong here?

8 comments
Comment actions Permalink

I don't think you can use a value of type Boolean directly as the state of a component. You mentioned a wrapper class - could you please show how you tried to define it?

0
Comment actions Permalink

Hi Dmitry,

I just made a public wrapper class with one boolean value:

 
public class StateWrapper {
    public boolean value;

    public StateWrapper() {
        value = true;
    }
}


Accordingly, I modified the classheader and the getState and loadState methods:

 
public class StorageTestSettingsPage implements Configurable, ModuleComponent, PersistentStateComponent<StorageTestSettingsPage.StateWrapper>

 
public StorageTestSettingsPage.StateWrapper getState() {
   StateWrapper wrapper = new StateWrapper();
   wrapper.value = value;
   return wrapper;
}

public void
loadState(StorageTestSettingsPage.StateWrapper state) {
    this.value = state.value;
}


Note that my actual plugin is using a more versatile wrapper class with more values, but still is not saved into the .iml file.

0
Comment actions Permalink

Please try annotating the value field with the @Attribute annotation.


0
Comment actions Permalink

Do you mean com.intellij.util.xmlb.annotations.Attribute?

 
public class StateWrapper {
    @Attribute
    public boolean value
;

    public StateWrapper() {
        value = true;
    }
}


This didn't work either...

0
Comment actions Permalink

Yes. You need to specify the attribute name as the parameter to the annotation.

0
Comment actions Permalink

Like that?

 
public class StateWrapper {
    @Attribute(value = "value")
    public Boolean value;

    public StateWrapper() {
        value = true;
    }
}


This didn't work.

// edit: May this be caused by the limitation of filewatchers? I'm using Linux and everytime the application terminates it says:
WARN - api.vfs.impl.local.FileWatcher - Watcher terminated with exit code 0

0
Comment actions Permalink

Found the correct way of annotating the field:

 
public class StateWrapper {
    @Attribute("testvalue")
    public boolean value;

    public StateWrapper() {
        value = true;
    }

}

Still doesn't work. I attached the whole project. Could you take a look at it?



Attachment(s):
StorageTest.zip
0
Comment actions Permalink

Figured it out myself. The name attribute of the @State annotation has to match the name of the component.

// edit not true... but it works right now. Maybe it has something to do with the wrapper placed inside the class...

// edit2 The fields in the Wrapper have to be non final. I did set the values via a constructor and each field to final. Because of that, the values could not be set by the storage mechanism.

1

Please sign in to leave a comment.