Brutus
Brutus

Reputation: 33

org.springframework.beans.NotWritablePropertyException. Invalid property <blah> is not writable or has an invalid setter method

I have the requirement to remove all passwords and encryption keys from the source code of my project. I'm struggling to get this to work in my spring-servlet.xml file. This worked before I tried making the change:

I want to move the jdbc_server_properties file to the filesystem and include the key in the file.

This is my last (of at least 25) attempt at getting this to work.

<bean id="propertyConfigurer" class="org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer">
        <constructor-arg ref="standardEncryptor" />
        <property name="jdbcUsername" value="JDBC_USERNAME" />
        <property name="jdbcPassword" value="JDBC_PASSWORD" />
        <property name="jdbcUrl" value="JDBC_URL" />
        <property name="jdbcDriver" value="JDBC_DRIVER" />
        <property name="locations">
            <list>
                <value>file:///${USERPROFILE}/credentials/jdbc_server.properties</value>
            </list>
        </property>
</bean>

<bean id="standardEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="config" ref="environmentVariablesConfiguration" />
</bean>

<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
        <property name="algorithm" value="PBEWithMD5AndDES" />
        <property name="passwordSysPropertyName" value="ENCRYPTION_PASSWORD" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="${jdbcDriver}" p:url="${jdbcUrl}"
        p:username="${jdbcUsername}" p:password="${jdbcPassword}">
</bean>

Using the above configuration, I get a NotWritablePropertyException exception. I've seen tons of posts on this issue but not where both the properties and encryption key are in a file on the filesystem. When this was working and the properties were read from a file in the classpath, there were no getters/setters for jdbcUsername (or the other properties) so I don't know why it's failing in this way now.

I tried adding the getters and setters (as String) to my BaseDaoImpl class but I still get the same error so if I'm supposed to add them, I'm not sure where they go.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'propertyConfigurer' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'jdbcUsername' of bean class [org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer]: Bean property 'jdbcUsername' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1568)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276)
    at ...

Upvotes: 0

Views: 1482

Answers (1)

jccampanero
jccampanero

Reputation: 53441

That is probably because jdbcUsername is not a property of EncryptablePropertyPlaceholderConfigurer.

Please, try something like this (just remove the jdbc* properties from the EncryptablePropertyPlaceholderConfigurer configuration, and use it directly in your dataSource bean):

<bean id="propertyConfigurer" class="org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer">
        <constructor-arg ref="standardEncryptor" />
        <property name="locations">
            <list>
                <value>file:///${USERPROFILE}/credentials/jdbc_server.properties</value>
            </list>
        </property>
</bean>

<bean id="standardEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="config" ref="environmentVariablesConfiguration" />
</bean>

<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
        <property name="algorithm" value="PBEWithMD5AndDES" />
        <property name="passwordSysPropertyName" value="ENCRYPTION_PASSWORD" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="${JDBC_DRIVER}" p:url="${JDBC_URL}"
        p:username="${JDBC_USERNAME}" p:password="${JDBC_PASSWORD}">
</bean>

Assuming your jdbc_server.properties file contains the required information:

JDBC_USERNAME=ENC(...)
JDBC_PASSWORD=ENC(...)
JDBC_URL=ENC(...)
JDBC_DRIVER=your.jdbc.driver

Upvotes: 1

Related Questions