Spring Inject boolean value from property file using XML is always false - java

I am trying to inject boolean property from property file. the value of the attribute is alway false
the property
use.virtual.wallet=true
The xml configuration
<bean id="proxyUtil" class="com.util.ProxyServiceUtility">
<property name="useVirtualWallet" value="${use.virtual.wallet}" />
</bean>
the bean
public class ProxyServiceUtility {
private boolean useVirtualWallet;
public void setUseVirtualWallet(boolean useVirtualWallet) {
this.useVirtualWallet = useVirtualWallet;
}
public boolean isUseVirtualWallet() {
return useVirtualWallet;
}
}
useVirtualWallet is alway false

You have to load your properties file into Spring context using PropertyPlaceholderConfigurer.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>

The problem fixed using this workaround, instead of injecting boolean, I injected String and then converted that String to boolean on the setter
public void setUseVirtualWallet(String useVirtualWallet) {
this.useVirtualWallet = Boolean.parseBoolean(useVirtualWallet);
}

Another variant
<beans
xmlns:context="http://www.springframework.org/schema/context">
<context:property-placeholder location="classpath:com/foo/jdbc.properties"/>
...
<beans>

Related

Spring bean creation failed. Can parameter type of the setter be parent of the return type of the getter?

I am facing this exception while creating bean of datasource from DBCP2. Exception is
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'connectionInitSqls' of bean class [org.apache.commons.dbcp2.BasicDataSource]: Bean property 'connectionInitSqls' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
here is my bean configuration
<bean id="fileStore_dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" lazy-init="true">
<!-- Just that property which causes problem -->
<property name="connectionInitSqls">
<list>
<value>#{filestore.jdbc.connectionInitSql}</value>
</list>
</property>
</bean>
Here is the setter and getter code for connectionInitSqls in BasicDataSource class. version of DBCP2 is 2.1.1
private volatile List<String> connectionInitSqls;
public List<String> getConnectionInitSqls() {
final List<String> result = connectionInitSqls;
if (result == null) {
return Collections.emptyList();
}
return result;
}
public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
if (connectionInitSqls != null && connectionInitSqls.size() > 0) {
ArrayList<String> newVal = null;
for (final String s : connectionInitSqls) {
if (s != null && s.trim().length() > 0) {
if (newVal == null) {
newVal = new ArrayList<>();
}
newVal.add(s);
}
}
this.connectionInitSqls = newVal;
} else {
this.connectionInitSqls = null;
}
}
You can see that argument in setter is Collection which is Super type of List. But I dont know why spring could not instantiate the bean. Is this Spring problem or Bug in DBCP2 code. Can we give parent type of property in setter argument?
How can I resolve this problem? Any Help would be appreciated.
Spring will use reflection to find the setter property. So it will find the setter using setConnectionInitSqls and argument list because of the property type(which it will find from getter method getConnectionInitSqls) and it will not find therefore the exception.
Exception message is self explanatory now. Note that the property may not exist at all. Spring just works with getters and setters. It finds the appropriate setter method using the getter method's( which is easy to find just prefix with get and no arg method) return value type.
Bean property 'connectionInitSqls' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?`
you can try using MethodInvokingFactoryBean.
<bean id="fileStore_dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" lazy-init="true">
</bean>
<bean id="customInjector"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="fileStore_dataSource" />
<property name="targetMethod">
<value>setConnectionInitSqls</value>
</property>
<property name="arguments">
<list>
<value>#{filestore.jdbc.connectionInitSql}</value>
</list>
</property>
</bean>
Alternative way:
I would prefer this as it is SAFER. Reason being all properties are set during the instantiation phase itself. And then wiring between the beans happen. In the previous case it may be error prone because setting connectionInitSqls happens at a different time and chances are that connections might have already been created(without looking into the internals of the implementation of BasicDataSource).
public class CustomBasicDataSource extends BasicDataSource{
public void setConnectionInitSqls(List<String> connectionInitSqls) {
super.setConnectionInitSqls(connectionInitSqls);
}
}
replace with this class in xml
<bean id="fileStore_dataSource"
class="org.company.somepackage.CustomBasicDataSource" destroy-method="close" lazy-init="true">
...<!-- rest remain same-->
</bean>
Try ${ instead of #{
<property name="connectionInitSqls">
<list>
<value>${filestore.jdbc.connectionInitSql}</value>
</list>
</property>

Extract specific attribute from flat file item writer

I have an object returned from item processor.
public class PcdRateMapper
{
private Pcdrate pcdRate;
private Boolean isValidPcdRate;
public PcdRateMapper ()
{
// pcdRate = new Pcdrate ();
}
public Pcdrate getPcdRate ()
{
return pcdRate;
}
public void setPcdRate (Pcdrate pcdRate)
{
this.pcdRate = pcdRate;
}
public Boolean getIsValidPcdRate ()
{
return isValidPcdRate;
}
public void setIsValidPcdRate (Boolean isValidPcdRate)
{
this.isValidPcdRate = isValidPcdRate;
}
Now i want to extract only Pcdrate object values in my item writer. How can I do this. Currently I'm using following spring configuration but getting invalid property exception. Thanks in advance.
<
property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value="," />
<property name=""></property>
<property name="fieldExtractor">
<bean
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<property name=""></property>
<property name="names"
value="company, subcoy" />
</bean>
</property>
</bean>
</property>
The invalid property exception may stem from
<property name=""></property>
where the property name is an empty string. You have that twice in the code above, remove it.
Your xml structure seems to be invalid, see spring_bean_definition
to see how it should look like.
On the bean of type BeanWrapperFieldExtractor you must set the property 'names' to the names of properties that you want to extraxt, in your case 'pcdRate'.
It should be configured like this :
<bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<property name="names" value="pcdRate" />
</bean>

Spring Dependency injection with factory(dynamic value)

I'm new to spring.
I've a rulefactory, which would return an instance from a static method
based on the type value
Now i'll get the type from the main methods, argument.
Now i would like to pass the argument type to the factory method getInstance
type argument.
how to do that.
/* Factory class, getInstance will return a subtype of RuleEvaluation, for simplicity, i've not
provided the Implementation class for SingleRuleEvaluation and MassRuleEvaluation. Basically both the classes implements RuleEvaluation */
public class RuleEvalFactory {
public static RuleEvaluation getInstance(String type) {
if (type != null && type.equals("Single")) {
return new SingleRuleEvaluation();
} else if (type != null && type.equals("mass")) {
return new MassRuleEvaluation();
}
return null;
}
}
/* My Main class , i need to get an instance of the RuleEvaluation here based on the type(dyamic)
dont know how to do it.
*/
public class MyApp {
public static void main(String args[]) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Spring-All-Module.xml");
String type = args[0];
/* i want to pass the above type String to the factory method and get the instance how to do that */
RuleEvaluation re = (HarmonyService) context.getBean("rulefactory") ;
}
}
/* my Spring xml configuration file */
Spring xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="instanceMethodFactory" class="test.factory.RuleEvalFactory"> </bean>
<!-- i dont know how to pass the dynamic type from the Myapp main
method into this constructory argument -->
<bean id="rulefactory" factory-bean="instanceMethodFactory" factory-method="getInstance">
<constructor-arg index="0"> </constructor-arg>
</bean>
</beans>
Please give the code in Spring xml and Myapp main method how to inject the type into the factory method's getInstance.
Regards,
Raghu
You need to specify in the bean the constructor argument,
<bean id="myBean" class="A" scope="prototype">
<constructor-arg value="0"/> <!-- dummy value -->
</bean>
And then pass the value to bean factory,
getBean("myBean", argument);

How to conditionally initialization a class via spring

How to conditionally initialization a class via spring?
If some condtion is true then i want one argument to be passed else some other
argument
<bean id="myFactory" class="Factory">
if something then
<constructor-arg>
<util:map>
<!-- configure your map here, or reference it as a separate bean -->
<entry key="java.lang.String" value="key">....</entry>
</util:map>
</constructor-arg>
else
<constructor-arg>
<util:map>
<!-- configure your map here, or reference it as a separate bean -->
<entry key="java.lang.String" value="key">....</entry>
</util:map>
</constructor-arg>
</bean>
How?
Spring Expression Language might do the trick for you. link
You can do it exactly the way that you have specified. Define a FactoryBean this way, say for eg. For generating a Customer Bean:
public class CustomFactoryBean implements FactoryBean<Customer>{
private int customProperty;
public int getCustomProperty() {
return customProperty;
}
public void setCustomProperty(int customProperty) {
this.customProperty = customProperty;
}
#Override
public Customer getObject() throws Exception {
if (customProperty==1)
return new Customer("1", "One");
return new Customer("999", "Generic");
}
#Override
public Class<?> getObjectType() {
return Customer.class;
}
#Override
public boolean isSingleton() {
return true;
}
}
That is basically it, now based on how you inject in th properties of the factory bean, the actual bean instantiation can be controlled in the getObject method above

Spring 3: disable SpEL evaluation of a bean property value?

We're in the process of updating our apps from Spring 2.5 to 3.0 and we've hit a problem with the new SpEL evaluation of bean properties.
We've been using an in-house templating syntax in one module which unfortunately uses the same "#{xyz}" markup as SpEL. We have a few beans which take string's containing these expressions as properties but spring assumes they are SpEL expressions and throws a SpelEvaluationException when it tries to instantiate the bean.
e.g.
<bean id="templatingEngine" class="com.foo.TemplatingEngine">
<property name="barTemplate" value="user=#{uid}&country=#{cty}"/>
</bean>
Is it possible to disable SpEL evaluation, ideally per-bean, but alternatively for the whole application context?
Alternatively is there a way to escape the values?
Thanks,
Stephen
Completely disable SpEL evaluation by calling the bean factory setBeanExpressionResolver method passing in null. You can define a BeanFactoryPostProcessor to do this.
public class DisableSpel implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory)
throws BeansException
{
beanFactory.setBeanExpressionResolver(null);
}
}
Then define this bean in the application context.
<bean class="com.example.spel.DisableSpel"/>
Well what you could do is re-define the expression language delimiters.
I would say the way to do this is through a special bean that implements BeanFactoryPostProcessor (thanks to inspiration by Jim Huang):
public class ExpressionTokensRedefiner implements BeanFactoryPostProcessor{
private BeanExpressionResolver beanExpressionResolver;
public void setBeanExpressionResolver(
final BeanExpressionResolver beanExpressionResolver){
this.beanExpressionResolver = beanExpressionResolver;
}
#Override
public void postProcessBeanFactory(
final ConfigurableListableBeanFactory beanFactory)
throws BeansException{
beanFactory.setBeanExpressionResolver(createResolver());
}
private String expressionPrefix = "${";
private String expressionSuffix = "}";
public void setExpressionPrefix(final String expressionPrefix){
this.expressionPrefix = expressionPrefix;
}
public void setExpressionSuffix(final String expressionSuffix){
this.expressionSuffix = expressionSuffix;
}
private BeanExpressionResolver createResolver(){
if(beanExpressionResolver == null){
final StandardBeanExpressionResolver resolver =
new StandardBeanExpressionResolver();
resolver.setExpressionPrefix(expressionPrefix);
resolver.setExpressionSuffix(expressionSuffix);
return resolver;
} else{
return beanExpressionResolver;
}
}
}
Define it as a bean like this:
<bean class="foo.bar.ExpressionTokensRedefiner">
<property name="expressionPrefix" value="[[" />
<property name="expressionSuffix" value="]]" />
</bean>
or like this:
<!-- this will use the default tokens ${ and } -->
<bean class="foo.bar.ExpressionTokensRedefiner" />
or use a custom resolver:
<bean class="foo.bar.ExpressionTokensRedefiner">
<property name="beanExpressionResolver">
<bean class="foo.bar.CustomExpressionResolver" />
</property>
</bean>
Now you can leave your definitions untouched and if you want to use SpEL, use the new delimiters.
EDIT: now I did test it and it actually works.
<bean class="foo.bar.ExpressionTokensRedefiner">
<property name="expressionPrefix" value="[[" />
<property name="expressionSuffix" value="]]" />
</bean>
<bean class="foo.bar.FooFritz">
<property name="fizz" value="[[ systemProperties['user.home'] ]]"></property>
<property name="fozz" value="[[ systemProperties['java.io.tmpdir'] ]]"></property>
<!-- this is what it would normally choke on -->
<property name="fazz" value="#{ boom() }"></property>
</bean>
Test code:
final ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("classpath:foo/bar/ctx.xml");
context.refresh();
final FooFritz fooFritz = context.getBean(FooFritz.class);
System.out.println(fooFritz.getFizz());
System.out.println(fooFritz.getFozz());
System.out.println(fooFritz.getFazz());
Output:
/home/seanizer
/tmp
#{ boom() }
I am not a dab, but this mighbe of help.
https://issues.apache.org/jira/browse/CAMEL-2599

Categories