Concatenate string in spring xml configuration - java

I need to concatenate the string value of a spring bean, to an existing string, and then set it as an attribute of another bean:
<bean id="inet" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"><value>java.net.InetAddress</value></property>
<property name="targetMethod"><value>getLocalHost</value></property>
</bean>
<bean id="host" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="inet"/></property>
<property name="targetMethod"><value>getHostName</value></property>
</bean>
At this point, I have the hostname, in the 'host' bean. I now need to concatenate it and pass it to the publishedEndpointUrl attribute. Something like this:
<jaxws:endpoint
id="foo"
publishedEndpointUrl= "http://" + host + "/Foo"
implementor="com.example.v1.foo"
address="/v1/Foo"/>
How is this done using spring xml configuration?

You could use Spring-EL and factory-method:
<bean id="localhost" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="publishedUrl" class="java.lang.String">
<constructor-arg value="#{'http://' + localhost.hostName + '/Foo'}" />
</bean>
<jaxws:endpoint
...
publishedEndpointUrl="#publishedUrl"
...
EDIT:
The jaxws:endpoint tag appears to be able to reference bean values by using the #beanId notation but does not like Spring-EL. So by constructing a String bean, we get around this and it still looks fairly neat.

You need to look at PropertyPlaceholderConfigurer. This allows you define global properties, which can either come from a properties file, or in your case, you can define a default value, in which case it's just a global property. The following will work:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
<property name="properties">
<props>
<prop key="driver">jdbc.oracle.Driver</prop>
<prop key="dbname">fred</prop>
</props>
</property>
<property name="locations">
<list>
<value>file:properties/application.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${driver}</value></property>
<property name="url"><value>jdbc:${dbname}</value></property>
</bean>
This means that you have default values for ${driver} and ${dbname}, which are used to define the data source. These values can be overridden in the application.properties file, or even as a -D option on the command line.

As jaxws:* namespace does not like Spring EL, an alternative could be to declare an EndpointImpl bean, instead of the jaxws:endpoint object.
It is some more work, but as pointed out in http://cxf.apache.org/docs/jax-ws-configuration.html, it is the actual implementation used by the namespace declaration.

You can mix propertyplaceholder vars and Spring EL:
<bean id="dataSource" class="xx.xxx.xxxxx.datasource.DataSourceWrapper" destroy-method="close">
<property name="dataSourceClassName" value="${db.dataSourceClassName}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="maximumPoolSize" value="${db.maxConnections}" />
<property name="connectionTimeout" value="${db.connectionTimeout}" />
<property name="dataSourceProperties">
<props>
<prop key="databaseName">${db.databaseName}</prop>
<prop key="serverName">${db.serverName}#{':'}${db.port}</prop>
</props>
</property>
Look at ${db.serverName}#{':'}${db.port} concat.

Related

Spring. How to add same property to multiple beans?

Consider I have something like this in beans.xml:
<bean id="emails" class="org.some.package.SomeClass">
<property name="emailList">
<list>
<value>pechorin#hero.org</value>
<value>raskolnikov#slums.org</value>
<value>stavrogin#gov.org</value>
<value>porfiry#gov.org</value>
</list>
</property>
</bean>
But I need to add emailList property into multiple beans. How can I do that without writing property to each bean? Can externalize property and inject it into each bean?
I expect something like:
<property name="commonProp">
<list>
<value>pechorin#hero.org</value>
<value>raskolnikov#slums.org</value>
<value>stavrogin#gov.org</value>
<value>porfiry#gov.org</value>
</list>
</property>
<bean id="emailsOne" class="org.some.package.ClassOne">
<property name="emailList" ref="commonProp" />
</bean>
<bean id="emailsTwo" class="org.some.package.ClassTwo">
<property name="emailList" ref="commonProp" />
</bean>
You can do it using: util:list
<util:list id="myList" value-type="java.lang.String">
<value>foo</value>
<value>bar</value>
</util:list>
Then use this myList reference in other beans.

How can I use environment variable in hibernate config file?

I am currently using database parameters in hibernate(Version 4.0.1) file through properties file.
I want to use some database parameters from environment variable. How can I fetch values from java files and set in to xml files before that loads in context.
<bean id="propertyConfigurer"
class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="locations">
<list>
<value>classpath:/test/demo/prop/DataParam.properties</value>
</list>
</property>
</bean>
<bean id="data" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${driverClass}</value>
</property>
<property name="jdbcUrl">
<value>${dbconnecturl}</value>
</property>
.
.
.
</beans>
I got some idea to make an object of Configuration class but I don't know where to write that code and how it would be implemented.
You need to use spring expression language to configure the properties from OS environemnt variables as shown below:
<bean id="propertyConfigurer"
class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="locations">
<list>
<value>classpath:/test/demo/prop/DataParam.properties</value>
</list>
</property>
</bean>
<bean id="data" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>#{ systemProperties['driverClass']}</value>
</property>
<property name="jdbcUrl">
<value>#{ systemProperties['dbconnecturl']}</value>
</property>
.
.
.
</beans>
You can use as <property name="username" value="#{systemProperties['dbUsername']}"/> for instance.
The variable systemProperties is predefined, you can see Xml Based Configuration for more details.

Spring Cfg+Hibernate Cfg and Anotations

I want to make a test with HQL but the mapping tables is with Annotations.
Hibernate configuration file is in the /WEB-INF/spring-config-ws.xml :::>
<!-- Activate transaction declarations with annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Property files application uses -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- JNDI DataSource -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${dataSource.jndiName}" />
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="true"/>
<property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
<property name="packagesToScan">
<list>
<value>es.sergas.rprof.profesional.domain</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.default_schema">${hibernate.default_schema}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
</props>
</property>
</bean>
<!-- Transaction manager for Hibernate SessionFactory -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
When I run a list, I get that you do not find the hibernate cfg:
hibernate.cfg.xml not found
I just want to list a mapped class with annotations, but HQL
I feel my level of English is so low. Thank you
Make sure your hibernate.cfg.xml is inside src/main/resources, if the file is not there you need to specify the right location, so put it inside this folder that your problem will be solved.
Note that we don’t have to explicitly mention the mapping or configuration or properties
files, because the Hibernate runtime looks for default filenames, such as hibernate.
cfg.xml or hibernate.properties, in the classpath and loads them. If we have a nondefault
name, make sure you pass that as an argument—like configure("my-hibcfg.
xml"), for example.

Calling method in Bean property attribute

I have a simple bean tag in the bean xml file as shown below. This is just a dummy values
<bean id="myBeanId" class="myBeanClass">
<property name="myProperty" value=${myPassword} />
</bean>
<bean id ="myOtherBeanId" class="myOtherBeanClass">
<property name="myOtherProperty" ref="myBeanId">
</bean>
myPassword is a variable names stored in a separate properties file. Now, I instead of storing the direct value of myPassword from the properties file, I will have encrypted string in the property file and I want to call my custom written Decrypt method on myPassword property instead. something like this.
<bean id="myBeanId" class="myBeanClass">
<property name="myProperty" value=com.xxx.Security.Decrypt(${myPassword}) />
</bean>
How can I do this?
Use the MethodInvokingFactoryBean if you want to invoke another bean's method and use the returned object as a bean.
<bean id="securityBean" class="com.xxx.Security">
</bean>
<bean id="myBeanId" class="myBeanClass">
<property name="myProperty">
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="securityBean"/></property>
<property name="targetMethod"><value>Decrypt</value></property>
<property name="arguments">
<list>
<value>${myPassword}</value>
</list>
</property>
</bean>
</property>
</bean>
How about Using with jaspyt,
Properties file entry
password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)
Bean Entry
<bean id="myBeanId" class="myBeanClass">
<property name="myProperty" value=${password} />
</bean>
Source : http://www.jasypt.org/spring31.html

how to get a spring declared datasource in an xml config file

i have a spring datasource which looks like this:
<bean id="dataSource1" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database1.url}" />
<property name="username" value="${database1.username}" />
<property name="password" value="${database1.password}" />
</bean>
i need to make this available on jndi or jee. some related things:
<bean id="dataSourceJNDI1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/dataSource1"/>
<property name="beanClassLoader" ref="dataSource1"></property>
</bean>
or maybe :
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/database1" />
not sure how to get the jndi or jee working with the dbcp. any help would be appreciated.
thanks in advance.
ps: guys this is a special needl. so i have to do it like this. please dont post unnecessary advices saying why i should use tomcat server as datasource. i am aware of setting datasource that way. i repeat again this is a special need. also please dont provide me java code solutions, not required.
ps: those who dont know how to do it, please do not occupy the space of this post saying its not possible. if you dont know the answer no need to post and junk the post.
You would need to bind the DataSource to the JNDI tree. You would need to supply the parameters for connecting to the local JNDI tree. JndiTemplate can do this. Some of the JNDI environment properties probably won't be necessary for a local InitialContext. I think "java.naming.factory.initial" is the only required. The other are for connecting to an out of process JNDI server:
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.provider.url">${jndi.provider.url}</prop>
<prop key="java.naming.factory.initial">${jndi.factory.initial}</prop>
<prop key="java.naming.security.principal">${jndi.security.principal}</prop>
<prop key="java.naming.security.credentials">${jndi.security.credentials}</prop>
</props>
</property>
</bean>
<bean factory-bean="jndiTemplate" factory-method="bind">
<constructor-arg type="java.lang.String" value="java:com/env/DataSoure"/>
<constructor-arg type="java.lang.Object" ref="dataSource"/>
</bean>
If you are performing a JNDI lookup in the same Spring context, you will either need to have the JNDI bean depends-on this lookup bean or make the JNDI lookup lazy so that it will perform the lookup on first use.
Since you are using jndi you have to declare the datasource as a jndi source.
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/database1" />
<bean id="dataSource1" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="dataSource" ref="dataSource" />
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database1.url}" />
<property name="username" value="${database1.username}" />
<property name="password" value="${database1.password}" />
</bean>
That should work assuming your bean definition for dataSource1 is correct.

Categories