How to read properties fragment from Spring configuration [duplicate] - java

This question already has answers here:
Reading a List from properties file and load with spring annotation #Value
(17 answers)
Closed last year.
Is it possible to read fragment of an array by #Value (Spring 5)?
Something like this:
Input
data.properties :
list.numbers=1,2,3
Read
#Value("${list.numbers[0]}")
int firstNumber;
Output
firstNumber=1

You can split and get the first element.
#Value("#{'${list.numbers}'.split(',')[0]}")
int firstNumber;

A long time ago, I have used bean injection with XML configuration.
You can read that blog article and using spring-core, spring-beans and spring-context-support dependencies.
Below you'll find the XML config of that bean injection with the <bean ref="beanListItemId"> (here : song1, song2, etc.) inside your bean list (here the list container is album):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="song1" class="org.kodejava.spring.core.Song">
<property name="title" value="I Saw Her Standing There" />
<property name="writer" value="Beatles" />
</bean>
<bean id="song2" class="org.kodejava.spring.core.Song">
<property name="title" value="Misery" />
<property name="writer" value="Beatles" />
</bean>
<bean id="song3" class="org.kodejava.spring.core.Song">
<property name="title" value="Anna (Go to Him)" />
<property name="writer" value="Beatles" />
</bean>
<bean id="album" class="org.kodejava.spring.core.Album">
<property name="title" value="Please Please Me" />
<property name="year" value="1963" />
<property name="songs">
<list>
<ref bean="song1" />
<ref bean="song2" />
<ref bean="song3" />
</list>
</property>
</bean>
</beans>

Related

Properties file value is not being read in xml

I was learning Java Spring and faced a problem while working with properties file. Property File value is not being read in xml file and throwing exception.
The XML file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="triangle1" class="com.springtest.shapes.Triangle">
<property name="pointA" ref="zeroPoint"/>
<property name="pointB" ref="point2" />
<property name="pointC" ref="point3" />
</bean>
<bean id="zeroPoint" class="com.springtest.shapes.Point">
<property name="x" value="#{pointA.pointX}" />
<property name="y" value="#{pointA.pointY}" />
</bean>
<bean id="point2" class="com.springtest.shapes.Point">
<property name="x" value="5" />
<property name="y" value="2" />
</bean>
<bean id="point3" class="com.springtest.shapes.Point">
<property name="x" value="-20" />
<property name="y" value="10" />
</bean>
<bean class="com.springtest.main.DisplayNameBeanPostProcessor"/>
<bean class="org.SpringFramework.beans.factory.config.PropertyPlaceHolderConfigurer">
<property name="locations">
<value>classpath:pointconfig.properties</value>
</property>
</bean>
</beans>
The Property file is as follows:
pointA.pointX=0
pointA.pointY=0
The following exception is being shown:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'pointA' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:100)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:87)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:52)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:111)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:270)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:163)
... 28 more
The Project Structure is also provided
Thanks in advance
I finally get the answer after continuous digging. Thanks Manish Shen from Youtube.
My Problem was,
I named the class name wrong. This class name was used in previous version of spring. The new class name is "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer".
The Value in the property of spring.xml should be written as "${pointA.pointX}" instead of "#{pointA.pointX}".
I am sharing the screenshot from where i got the answer.

How do I set Spring Batch jobParameters in xml?

This job.xml works great when using parameters.
<beans>
<bean id="testFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
<property name="resource" value="#{jobParameters['paramFileOuput']}"/>
<property name="shouldDeleteIfExists" value="true" />
<property name="lineAggregator">
...
</property>
</bean>
</beans>
But what if I don't want to use job parameters but instead use Spring profiles...
<beans>
<bean id="testFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
<property name="resource" ref="testFileOutput"/>
<property name="shouldDeleteIfExists" value="true" />
<property name="lineAggregator">
....
</property>
</bean>
<beans profile="dev">
<bean id="testFileOutput" class="java.lang.String">
<constructor-arg type="java.lang.String" value="file:c:/temp/testfile.txt" />
</bean>
</beans>
<beans profile="prod">
<bean id="testFileOutput" class="java.lang.String">
<constructor-arg type="java.lang.String" value="file:pathtoprod.txt" />
</bean>
</beans>
</beans>
This appears to work. But this just doesn't feel right. Is there a way to set the parameter in the xml using profiles?
Something along these lines (this obviously doesn't work)
<beans profile="dev">
<setJobParameter key="testFileOuput" value="file:c:/temp/testfile.txt" />
</beans>
I can use any version of spring or springbatch.
How about this:
public FileOutput {
private String filename;
...
}
and
<beans profile="dev">
<bean id="testFileOutput" class="FileOutput " c:filename="file:pathtoprod.txt">
</beans>
Unluckily, you cant use p/c namespace with java.lang.String, thats why you need a little helper class. Anyway, the solution would shrink your context.xml a few lines and looks more similar to your desired solution.

Spring: MethodInvokingFactoryBean calls wrong method

I need to do the following Java line in XML:
usersConnectionRepository.setConnectionSignUp(new AccountConnectionSignUp());
So I did this:
<bean id="usersConnectionRepository"
class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository"
scope="singleton">
<constructor-arg ref="dataSource" />
<constructor-arg ref="connectionFactoryLocator" />
<constructor-arg ref="textEncryptor" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>
<bean id="accountConnectionSignUp" class="edu.kit.tm.cm.ksc.config.AccountConnectionSignUp" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="usersConnectionRepository" />
</property>
<property name="targetMethod">
<value>setConnectionSignUp</value>
</property>
<property name="arguments">
<list>
<ref local="accountConnectionSignUp" />
</list>
</property>
</bean>
The error occurs when the method is supposed to be called.
java.lang.NoSuchMethodException: com.sun.proxy.$Proxy12.setConnectionSignUp(edu.kit.tm.cm.ksc.config.AccountConnectionSignUp)
As you can see above, it's totally searching in the wrong package, and I have no idea why.
I have no idea how to debug this further. I'm inexperienced with Spring and it's XML-Notation. I hope someone can help me. Thank you.
UPDATE
As requested, the complete social.xml. Although, I do not think it is needed to solve this.
<?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:facebook="http://www.springframework.org/schema/social/facebook"
xmlns:twitter="http://www.springframework.org/schema/social/twitter"
xmlns:social="http://www.springframework.org/schema/social" xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/social/facebook http://www.springframework.org/schema/social/spring-social-facebook.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/social/twitter http://www.springframework.org/schema/social/spring-social-twitter.xsd
http://www.springframework.org/schema/social http://www.springframework.org/schema/social/spring-social.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<context:property-placeholder
location="classpath:/edu/kit/tm/cm/ksc/config/application.properties" />
<bean id="connectionFactoryLocator"
class="org.springframework.social.connect.support.ConnectionFactoryRegistry"
scope="singleton">
<property name="connectionFactories">
<list>
<bean
class="org.springframework.social.twitter.connect.TwitterConnectionFactory">
<constructor-arg value="${twitter.consumerKey}" />
<constructor-arg value="${twitter.consumerSecret}" />
</bean>
<bean
class="org.springframework.social.facebook.connect.FacebookConnectionFactory">
<constructor-arg value="${facebook.clientId}" />
<constructor-arg value="${facebook.clientSecret}" />
</bean>
</list>
</property>
<aop:scoped-proxy proxy-target-class="false" />
</bean>
<bean id="usersConnectionRepository"
class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository"
scope="singleton">
<constructor-arg ref="dataSource" />
<constructor-arg ref="connectionFactoryLocator" />
<constructor-arg ref="textEncryptor" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>
<bean id="accountConnectionSignUp" class="edu.kit.tm.cm.ksc.config.AccountConnectionSignUp" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="usersConnectionRepository" />
</property>
<property name="targetMethod">
<value>setConnectionSignUp</value>
</property>
<property name="arguments">
<list>
<ref local="accountConnectionSignUp" />
</list>
</property>
</bean>
<bean id="connectionRepository" factory-method="createConnectionRepository"
factory-bean="usersConnectionRepository" scope="request">
<constructor-arg value="#{request.userPrincipal.name}" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="org.springframework.social.connect.web.ConnectController">
<!-- relies on by-type autowiring for the constructor-args -->
<!-- <constructor-arg ref="connectionFactoryLocator" /> -->
<!-- <constructor-arg ref="connectionRepository" /> -->
</bean>
<bean id="SimpleSignInAdapter" class="edu.kit.tm.cm.ksc.config.SimpleSignInAdapter" />
<bean class="org.springframework.social.connect.web.ProviderSignInController">
<!-- relies on by-type autowiring for the constructor-args -->
<constructor-arg ref="SimpleSignInAdapter" />
</bean>
Update 2
We wrote the Java-examples of the Spring-Social-Documentation to XML. In this case for the ProviderSigninControllers dependencies. Unfortunately there are no XML examples given in this case.
The simple solution is to change proxy-target-class to true in your usersConnectionRepository bean definition and add CGLIB to your class path.
If you don't need the proxying, remove it completely.
Explanation:
First, with this bean declaration
<bean id="usersConnectionRepository"
class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository"
scope="singleton">
<constructor-arg ref="dataSource" />
<constructor-arg ref="connectionFactoryLocator" />
<constructor-arg ref="textEncryptor" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>
Spring is creating a bean of type JdbcUsersConnectionRepository and wrapping it in a JDK proxy (since proxy-target-class is false). The serious shortcoming of JDK proxies, is that they only sub type interfaces.
In other words, Spring will see that the JdbcUsersConnectionRepository class implements the UsersConnectionRepository interface and use that when generating the Proxy. As the javadoc says
A proxy class extends java.lang.reflect.Proxy.
A proxy class implements exactly the interfaces specified at its creation, in the
same order.
So the generated proxy will be of type Proxy and UsersConnectionRepository.
This won't be an issue for MethodInvokingFactoryBean because it stores the reference in a field of type Object. However, when MethodInvokingFactoryBean tries to resolve the Method to invoke, it uses the target object's Class instance, ie. object.getClass(). Since the target object is actually of type Proxy, or com.sun.proxy.$Proxy12 to be exact, it does not have a JdbcUsersConnectionRepository#setConnectionSignUp method and that causes a NoSuchMethodException.

Why does Spring 3.x ignore certain placeholderPrefixes for PropertyPlaceholderConfigurer?

I have the bean definitions below. If I change the placeholderPrefix for the "exposeSystemProperties" bean to "${" and use that in the properties path of the second bean, it works. If I change it to anything but "%{" it doesn't work. I can't use any other string (e.g. "$sys{", "#[", etc.). I'm currently on 3.0.5.RELEASE.
Any thoughts as to why this is? To compound it all, I have a 3rd PropertyPlaceHolderConfigure, so only having two prefixes does not work.
<bean id="exposeSystemProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="placeholderPrefix"><value>$sys{</value></property>
<property name="order" value="10" />
</bean>
<bean id="localFileProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_NEVER" />
<property name="placeholderPrefix" value="%{" />
<property name="placeholderSuffix" value="}" />
<property name="order" value="20" />
<property name="locations">
<array>
<bean class="java.lang.String">
<constructor-arg><value>classpath:properties/$sys{deploy.env}/client.properties</value></constructor-arg>
</bean>
</array>
</property>
</bean>
Since what you need the prefix for is to control environment specific properties, this can be done by using system variables ( instead of a deploy.env property in your example ):
<value>classpath:properties/${ENV_SYSTEM:dev}/client.properties</value>
In this case it will always look under:
<value>classpath:properties/dev/client.properties</value>
by default, unless a ENV_SYSTEM system variable is set. If it is set to "qa", for example, it will automatically look under:
<value>classpath:properties/qa/client.properties</value>
Another approach, in case you are open to "look into the future" a bit, is to use Spring 3.1's PROFILE feature, where beans can be profile specific. For example:
<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
</jdbc:embedded-database>
</beans>
This dataSource will only be loaded in case a profile is set to dev:
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles( "dev" );
ctx.load( "classpath:/org/boom/bang/config/xml/*-config.xml" );
ctx.refresh();

Spring locale: can't get interceptors to work

I have a jsp file with 2 links which set a property lang to either en or de.
I also have a message that needs to be changed in the corresponding language either english or german.
I have the 2 property files with the codes. I made the configuration file for the locale.
I've tried different combination of classes and properties but I can never get the message changed.
This is my code:
jsp file:
Language : English|German
<h3>
<spring:message code="test" text="default text" />
</h3>
Current Locale : ${pageContext.response.locale} ---- ${pageContext.request.locale}
applicationContext.locale.xml file: (this is imported in applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="WEB-INF/locale/welcome" />
<property name="cacheSeconds" value="-1" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en"/>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor"/>
</list>
</property>
</bean>
I have 2 property files:
welcome.properties and welcome_de.properties. Both have a code test and different values to it.
The problem is if I set the default Locale it will always take that. If I don't set it the locale resolver will take the locale of the request.
I can't set the locale of the response to be taken from the url parameter.
Do you have any suggestions?
Thanks :)
Check your code against the project you can download from the MVC Simplifications in Spring 3.0
https://src.springframework.org/svn/spring-samples/mvc-basic/trunk/

Categories