Inject all properties from PropertyPlaceholderConfigurer into a bean - java

I have a PropertyPlaceholderConfigurer that loads multiple properties files. I want to inject the merged properties map into a Spring Bean via config XML.
Can I do that and how?

You could just create a properties bean and use that for your PropertyPlaceholderConfigurer and your Config bean:
<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:default.properties</value>
<value>classpath:someother.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="myProperties" />
</bean>
<bean id="myConfigBean" class="my.pkg.Config">
<constructor-arg ref="myProperties" />
</bean>

Related

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:
the database username, encrypted password, URL and driver were defined in a file jdbc_server.properties as a classpath resource.
the encryption/decryption key was passed on start-up as -DENCRYPTION_PASSWORD=
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 ...
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

Override xml-defined spring bean in java-based configuration

I'm extending a complete product called Hippo CMS with my own REST interface. Hippo CMS is using Apache CXF for rest and acquires resources definitions from a spring bean defined somewhere in Hippo CMS sources. This definition look like this:
<bean id="jaxrsRestPlainResourceProviders" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.apache.commons.collections.ListUtils" />
<property name="targetMethod" value="union" />
<property name="arguments">
<list>
<ref bean="customRestPlainResourceProviders" />
<ref bean="defaultRestPlainResourceProviders" />
</list>
</property>
</bean>
<bean id="defaultRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
</list>
</property>
</bean>
<!-- Default empty list of custom plain resource providers to be overriden. -->
<bean id="customRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
</list>
</property>
</bean>
I need to override customRestPlainResourceProviders bean with my own bean. It works fine from XML configuration looking like this:
<bean id="customRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<bean class="org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider">
<constructor-arg>
<bean class="com.xxx.rest.FolderStructureResource"/>
</constructor-arg>
</bean>
</list>
</property>
</bean>
But it doesn't work if I define a bean in Java configuration class (which in the case of other beans works completely fine):
#Bean(name = "customRestPlainResourceProviders")
public ListFactoryBean customRestPlainResourceProviders() {
ListFactoryBean listFactoryBean = new ListFactoryBean();
listFactoryBean.setSourceList(
Lists.newArrayList(
new SingletonResourceProvider(
new FolderStructureResource(repository())
)
)
);
return listFactoryBean;
}
Is there a way to override a bean defined in XML configuration with a bean created in Java configuration class?
What version of spring are you using? I believe this issues is addressed in 4.2.

How to enable ActiveMQ embedded kahadb using bean configuration

I need to enable local persistence of activemq embedded broker by enabling kahadb. How can i configure kahadb in bean xml file.
<bean id="producerBroker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop">
<property name="brokerName" value = "producerBroker"/>
<property name="persistent" value="true"/>
<property name="transportConnectorURIs">
<list>
<value>tcp://localhost:7005</value>
</list>
</property>
<property name="jmsBridgeConnectors">
<list>
<bean class="org.apache.activemq.network.jms.JmsQueueConnector">
<property name="outboundQueueConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="http://localhost:8090" />
</bean>
</property>
<property name="outboundQueueBridges">
<list>
<bean class="org.apache.activemq.network.jms.OutboundQueueBridge">
<constructor-arg value="qvsample"/>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
EDIT
ActiveMQ's default persistence db is kahoDb. this line <property name="persistent" value="true"/>made this. I need to know how to change this db to another. Moreover i need a good reference to configure spring xml file for activemq?
You can create a bean of org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter and inject it into your broker through persistenceAdapter property.
E.g.
<bean id="persistenceAdapter" class="org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter">
<property name="directory" value="D:\test"/>
</bean>
<bean id="producerBroker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop">
<property name="persistenceAdapter" ref="persistenceAdapter"/>
</bean>
You can use any other persistence adapter (e.g. leveldb) as long as it implements org.apache.activemq.store.PersistenceAdapter

How to inherit proxied object in XML bean configuration

I have an AOP proxy bean defined as follows:
<bean id="someService" class="..FactoryBean">
..
<property name="target">
<ref local="target" />
</property>
<property name="preInterceptors"><ref local="serviceInterceptors"/></property>
..
</bean>
a target bean:
<bean id="target" class=".." />
and a child to the target bean:
<bean parent="target">
<!-- set some properties -->
</bean>
I'd like to change the target bean to an anonymous bean, but maintain the child bean. The only problem is setting parent attribute of child bean to AOP proxy bean inherits from the factory bean and not the target bean. Is there a work around for this?
Not pretty, but it should work:
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="com.foo.bar.ExampleService" />
</property>
</bean>
<bean id="targetSource" factory-bean="proxy" factory-method="getTargetSource" />
<bean id="parent" factory-bean="targetSource" factory-method="getTarget" />
<bean parent="parent" />

Common value configuration in Spring XML

I have several Spring beans in which one of the property value for all of them are same String value. Is there a way where I can define this String in XML at one place and refer it in all beans at property value settings?
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
<bean id="nextBean" class="test.NextBean">
<property name="property2" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
How to set commonValue in a seperate place and refer it in both places?
Try like this.
<bean id="commonConfig" abstract="true">
<property name="commonField" value="CommonValue"></property>
</bean>
<bean id="class1" class="com.dataclass.Class1" parent="commonConfig">
<property name="field1" value="value1"></property>
</bean>
<bean id="class2" class="com.dataclass.Class2" parent="commonConfig">
<property name="field2" value="value2"></property>
</bean>
Class1 & Class2 having one common field name "commonField", parent attribute is use for this common purpose only.
In Spring this is called bean definition inheritance(this is not java class inheritance, above example Class1 & n Class not inheriting in their respective java file.)
For more detail, look at Spring doc's link.
I've never tried it before, but this should work
<bean id="commonProp" class="java.lang.String">
<constructor-arg name="original" value="yourString"></constructor-arg>
</bean>
Then, in every bean you need to reference it:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" ref="commonProp"></property>
</bean>
You can define your string properties in some "init_constants.properties" file. Then you should load properties file in spring xml:
<bean id="properties"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
<value>classpath:mail.properties</value>
<value>classpath:init_constants.properties</value>
</list>
</property>
</bean>
And after that you can inject this properties using xml:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="{$prop1}"></property>
<property name="commonProperty" value="commonValue"></property>
</bean>
or in code using #Value annotation:
#Value(value="${prop1}")
private String property1;
Well If commonValue is string then you can put it in properties file and read it using #Value annotation.

Categories

Resources