Java Spring IOC overriding property of bean - java

I need 3 beans, each with 3 properties 2 of them are related properties values from anothers beans but they differ in only 1 property. I have something like this:
<bean id="a" class="myClassPath" scope="prototype">
<property name='status' value='#{otherBean.myMethod()}'/>
<property name='code' value='#{otherBean.myOtherMethod()}'/>
<property name='typeOf' value='1'/>
</bean>
<bean id="b" class="myClassPath" scope="prototype">
<property name='status' value='#{otherBean.myMethod()}'/>
<property name='code' value='#{otherBean.myOtherMethod()}'/>
<property name='typeOf' value='2'/>
</bean>
<bean id="c" class="myClassPath" scope="prototype">
<property name='status' value='#{otherBean.myMethod()}'/>
<property name='code' value='#{otherBean.myOtherMethod()}'/>
<property name='typeOf' value='3'/>
</bean>
This code is very redundant. Can I if like define a bean and some kind override only the property typeOf?
UPDATE
the value of status and code are defined in others beans using Spring language this is in some way a example.

Take advantage of the bean template inheritance for a scenario like this:
<bean id="yourCommonProperties" abstract="true" scope="prototype">
<property name="status" value='#{otherBean.myMethod()}'/>
<property name="code" value='#{otherBean.myOtherMethod()}'/>
</bean>
Here we are not specifying the class but just sharing the common properties and refer this using parent attribute in each of the bean definition as:
<bean id="a" class="myClassPath" parent="yourCommonProperties" scope="prototype">
<property name='typeOf' value='1'/>
</bean>
<bean id="b" class="myClassPath" parent="yourCommonProperties" scope="prototype">
<property name='typeOf' value='2'/>
</bean>
<bean id="c" class="myClassPath" parent="yourCommonProperties" scope="prototype">
<property name='typeOf' value='3'/>
</bean>

Yup, just in your class definition do as follows:
...
private boolean status = true;
private int code = 13;
private int typeOf;
...
and then Spring config would be like:
<bean id="a" class="myClassPath" scope="prototype">
<property name='typeOf' value='1'/>
</bean>

For example use autowired="byName", and create beans with status and code names:
<bean id="status" class="java.lang.Boolean">
<constructor-arg value="true"/>
</bean>
<bean id="code" class="java.lang.Integer">
<constructor-arg value="13"/>
</bean>
<bean id="a" class="myClassPath" autowired="byName" scope="prototype">
<property name='typeOf' value='1'/>
</bean>
<bean id="b" class="myClassPath" autowired="byName" scope="prototype">
<property name='typeOf' value='2'/>
</bean>
<bean id="c" class="myClassPath" autowired="byName" scope="prototype">
<property name='typeOf' value='3'/>
</bean>

Related

dynamically replace the value to placeholder in config xml file in Spring Batch

I am using Spring Batch 2 version. I am reading data from database using JdbcCursorItemReader.I have successfully fetched the data and also written it to a file.
Below is itemReader bean defined in Job.xml File::
<bean id="itemReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="select u.ID, u.USER_LOGIN, u.PASSWORD, u.AGE from USERS u" />
</property>
<property name="rowMapper">
<bean class="com.example.UserRowMapper" />
</property>
</bean>
But the issue is,my query is quite big so I just want to keep that query out of xml file and get that query from other file or property file(.property,yaml or xml).
So that I can write xml code as below::
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="$sql_query" />
</property><property name="rowMapper">
<bean class="com.example.UserRowMapper" />
</property>
</bean>
What is best way to achieve this?
<bean id="myProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>path1.properties</value>
<value>path2.properties</value>
.....
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
...
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="${sql_query}" />
</property><property name="rowMapper">
<bean class="com.example.UserRowMapper" />
</property>
</bean>
path1.properties:
sql_query=value
PropertySourcesPlaceholderConfigurer is preffered in 3.1 and higher, instead of PropertyPlaceholderConfigurer
You can add sql in jobexecutioncontext by using job listener before step.

In which scenario do i need to provide spring class name as bean id value?

I need to configure xml file for DAO. So in my xml file, I have declared two entityManager Factory and I want to set one of them as default persistence unit. I have declared that part as below in my dao.xml
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
property name="defaultPersistenceUnitName" value="pumps-jpa"/>
</bean>
But, it didn't not work for me, it was not taking default persistence unit. I was getting error like this
No unique bean of type is defined: expected single bean but found 2:
After lot of searching, I found one code snippet in which they have mentioned bean id as spring class name i.e. org.springframework.context.annotation.internalPersistenceAnnotationProcessor, as shown below
<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
property name="defaultPersistenceUnitName" value="pumps-jpa"/>
</bean>
So, after mentioning this bean id, it is taking default persistence unit name. I want to know, why do I need to mention spring class (org.springframework.context.annotation.internalPersistenceAnnotationProcessor) as bean id? Is it a kind of hack or something?
Whole dao.xml is declared below
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:${catalina.base}/conf/pumps-dbconfig.properties"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${jdbc.driver}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.user}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="initialPoolSize"><value>10</value></property>
<property name="minPoolSize"><value>10</value></property>
<property name="maxPoolSize"><value>${jdbc.maxConnections}</value></property>
<property name="maxIdleTimeExcessConnections"><value>600</value></property>
<!-- <property name="timeout"><value>0</value></property> --> <!-- 0 means: no timeout -->
<property name="idleConnectionTestPeriod"><value>60</value></property>
<property name="acquireIncrement"><value>5</value></property>
<property name="maxStatements"><value>0</value></property> <!-- 0 means: statement caching is turned off. -->
<property name="numHelperThreads"><value>3</value></property> <!-- 3 is default -->
<property name="unreturnedConnectionTimeout"><value>0</value></property>
<property name="debugUnreturnedConnectionStackTraces"><value>true</value></property>
<property name="testConnectionOnCheckout"><value>true</value></property>
</bean>
<!--
Configuration for Hibernate/JPA
-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="pumps-jpa" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- DEFAULT PERSISTENCE UNIT DECLARATION -->
<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="defaultPersistenceUnitName" value="pumps-jpa"/>
</bean>
<bean id="r-dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${r-jdbc.driver}</value>
</property>
<property name="jdbcUrl">
<value>${r-jdbc.url}</value>
</property>
<property name="user">
<value>${r-jdbc.user}</value>
</property>
<property name="password">
<value>${r-jdbc.password}</value>
</property>
<property name="initialPoolSize"><value>10</value></property>
<property name="minPoolSize"><value>10</value></property>
<property name="maxPoolSize"><value>${r-jdbc.maxConnections}</value></property>
<!-- <property name="timeout"><value>0</value></property> --> <!-- 0 means: no timeout -->
<property name="maxIdleTimeExcessConnections"><value>600</value></property>
<property name="idleConnectionTestPeriod"><value>60</value></property>
<property name="acquireIncrement"><value>5</value></property>
<property name="maxStatements"><value>0</value></property> <!-- 0 means: statement caching is turned off. -->
<property name="numHelperThreads"><value>3</value></property> <!-- 3 is default -->
<property name="acquireRetryAttempts"><value>3</value></property>
<property name="testConnectionOnCheckout"><value>true</value></property>
</bean>
<!--
Configuration for Hibernate/JPA
-->
<bean id="r-entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="pumps-jpa" />
<property name="dataSource" ref="r-dataSource" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="BaseDataConnection" class="com.myntra.commons.dao.impl.BaseDataConnection">
<property name="roEntityManagerFactory" ref="r-entityManagerFactory" />
</bean>
I think your original problem was not what you meant! By configuration you can refer to one of your Entity Manager's existing Persistence Unit implementations as 'the default persistence unit'! You can do this in your XML config! persistence.xml in JPA is your persistence config your beans (configuration) xml is an other option to point to some of the defined persistence units. Please post your whole config xml ...
For the rest of your problem with the Bean ID:
There is already a Bean in your container initialised with the same name.
The Container is using the Bean Id as a unique Id of your identifiable code fragment! If you use another name then your container will initialise another bean instance of the same class and give it the other name. However as I pointed out above this is not related to your problem! (Even if you can bypass your existing bean implementations and redefine your config if you do not have other options!)

java.net.SocketException: Invalid argument with RestTemplate

I'm using RestTemplate in order to send a post request. Something like this:
restTemplate.postForObject(url, fetchImageDataRequest, SimpleImageHolder[].class);
When I create restTemplate like that:
restTemplate = new RestTemplate();
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
restTemplate.getMessageConverters().add(converter);
Everything works fine. But when I use RestTemplate that is created in spring.xml and defined like this:
<bean id="reHttpConnectionManager" class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
<property name="params">
<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
<property name="soTimeout" value="30000"/>
<property name="connectionTimeout" value="30000"/>
<property name="maxTotalConnections" value="300"/>
<property name="defaultMaxConnectionsPerHost" value="50"/>
</bean>
</property>
</bean>
<bean id="reRequestFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="3000" />
<constructor-arg>
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<constructor-arg>
<bean class="org.apache.commons.httpclient.params.HttpClientParams" />
</constructor-arg>
<property name="httpConnectionManager" ref="reHttpConnectionManager" />
<property name="state">
<bean class="org.apache.commons.httpclient.HttpState" />
</property>
</bean>
</constructor-arg>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="reRequestFactory" />
</bean>
I get an java.net.SocketException: Invalid argument exception. Trying to figure this issue.
The full stacke trace:
org.springframework.web.client.ResourceAccessException: I/O error: Invalid argument; nested exception is java.net.SocketException: Invalid argument
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:279)
I couldn't find what the problem was but I just removed the HttpParams bean from the constructor of the bean httpClient and removed completely the HttpState and now it works. The new XML looks like this:
<bean id="reHttpConnectionManager" class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
<property name="params">
<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
<property name="soTimeout" value="30000"/>
<property name="connectionTimeout" value="30000"/>
<property name="maxTotalConnections" value="300"/>
<property name="defaultMaxConnectionsPerHost" value="50"/>
</bean>
</property>
</bean>
<bean id="reRequestFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="3000" />
<constructor-arg>
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<property name="httpConnectionManager" ref="reHttpConnectionManager" />
</bean>
</constructor-arg>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="reRequestFactory" />
</bean>

Fail to create bean in spring suddently

I have encountered a problem of failed to create bean in spring suddenly. The webapp is already deployed and has been running for several months. However, below error message comes suddenly. It can be resolved by restarting the webapp, but comes again without any hints. Does anyone have any idea of this case?
Tomcat 6 is being used to host the webapp.
[2013/05/03 12:02:56:421 HKT] ajp-8009-42 org.ajax4jsf.webapp.BaseXMLFilter(227) - Exception in the filter chain
javax.servlet.ServletException: Error creating bean with name 'reportGenerationBean' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'scheduleBean' while setting bean property 'scheduleBean'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scheduleBean': Invocation of init method failed; nested exception is java.lang.ArrayIndexOutOfBoundsException
applicationContext.xml as below
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:property-placeholder location="classpath*:webapp.properties,classpath*:env_prod.properties"/>
<context:annotation-config />
<bean id="facesUtils" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod">
<value>com.webapp.util.FacesUtils.init</value>
</property>
<property name="arguments">
<list>
<value>com.webapp.config.SpringBeanEnum</value>
<value>com.webapp.config.FacesBeanEnum</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="inspectbookSessionFactory"/></property>
</bean>
<context:component-scan base-package="com.webapp.bo, com.webapp.service" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="hibernateDAO" abstract="true">
<property name="sessionFactory"><ref local="inspectbookSessionFactory"/></property>
</bean>
<!-- Temporary Setting -->
<bean id="ItemSearchBeanDao" class="com.webapp.dao.tmp.ItemSearchBeanDao" parent="hibernateDAO">
<property name="maxRecordNo" value="${no_of_record.order}"/>
</bean>
<bean id="BookedSearchBeanDao" class="com.webapp.dao.tmp.BookedSearchBeanDao" parent="hibernateDAO">
<property name="maxRecordNo" value="${no_of_record.booked}"/>
</bean>
<bean id="ScheduleBeanDao" class="com.webapp.dao.tmp.ScheduleBeanDao" parent="hibernateDAO"></bean>
<bean id="WhItemSearchBeanDao" class="com.webapp.dao.tmp.WhItemSearchBeanDao" parent="hibernateDAO">
<property name="maxRecordNo" value="${no_of_record.whItem}"/>
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="-secret-"/>
</bean>
<bean id="EmailUtil" class="com.webapp.util.EmailUtil">
<property name="mailSender" ref="mailSender"/>
</bean>
<bean id="freeMarkerTemplateMailer" class="com.webapp.bo.email.impl.FreeMarkerTemplateMailer">
<property name="mailSender" ref="mailSender"/>
</bean>
<bean id="emailService" class="com.webapp.bo.email.impl.EmailServiceImpl" >
<property name="orgunitDao" ref="OrgunitDAO"/>
<property name="contactMethodDao" ref="ContactMethodDAO"/>
<property name="mailer" ref="freeMarkerTemplateMailer"/>
</bean>
<bean id="scheduleEmail" class="com.webapp.bo.schedule.impl.ScheduleEmailImpl" >
<property name="orgunitDao" ref="OrgunitDAO"/>
<property name="scheduleBeanDao" ref="ScheduleBeanDao"/>
<property name="emailService" ref="emailService"/>
</bean>
<bean name="scheduleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.webapp.service.schedule.ScheduleJob" />
<property name="jobDataAsMap">
<map>
<entry key="scheduleEmail" value-ref="scheduleEmail" />
</map>
</property>
</bean>
<!-- JSF backing bean START -->
<bean id="vendorSearchBean" class="com.webapp.service.search.item.VendorSearchBean" scope="session">
<property name="maxRecordNo" value="${no_of_record.vendor}"/>
</bean>
<bean id="itemSearchBean" name="itemSearchBean" class="com.webapp.service.search.item.NewItemSearchBean" scope="session">
<property name="maxRecordNo" value="${no_of_record.order}"/>
<property name="popupBean" ref="popupBean"/>
</bean>
<bean id="itemSearchPopupBean" name="itemSearchPopupBean" class="com.webapp.service.search.item.NewItemSearchBean" scope="session">
<property name="maxRecordNo" value="${no_of_record.order}"/>
</bean>
<bean id="detailBean" class="com.webapp.service.detail.DetailBean" scope="session">
<property name="itemSearchBean" ref="itemSearchBean"/>
<property name="itemSearchPopupBean" ref="itemSearchPopupBean"/>
<property name="popupBean" ref="popupBean"/>
</bean>
<bean id="bookedSearchBean" class="com.webapp.service.search.booked.BookedSearchBean" scope="session">
<property name="maxRecordNo" value="${no_of_record.booked}"/>
</bean>
<bean id="scheduleConfirmBean" class="com.webapp.service.schedule.ScheduleConfirmBean" scope="session">
<property name="popupBean" ref="popupBean"/>
</bean>
<bean id="scheduleBean" class="com.webapp.service.search.schedule.ScheduleBean" scope="session">
<property name="popupBean" ref="popupBean"/>
</bean>
<bean id="dropBean" class="com.webapp.service.search.schedule.DropBean" scope="request">
<property name="scheduleBean" ref="scheduleBean"/>
</bean>
<bean id="inspectContactBean" class="com.webapp.service.detail.contact.InspectContactBean" scope="session">
<property name="detailBean" ref="detailBean"/>
</bean>
<bean id="inspectLocationBean" class="com.webapp.service.detail.contact.InspectLocationBean" scope="session">
<property name="detailBean" ref="detailBean"/>
</bean>
<bean id="whItemSearchBean" class="com.webapp.service.search.warehouse.WhItemSearchBean" scope="session">
<property name="maxRecordNo" value="${no_of_record.whItem}"/>
<!--<property name="propertiesUtil" ref="propertiesUtil"/>-->
</bean>
<!-- Autocomplete -->
<bean id="autocomplete" class="com.webapp.service.common.AutocompleteBean" scope="session"></bean>
<!-- PackingListBean -->
<bean id="packingListBean" class="com.webapp.service.common.PackingListBean" scope="session">
<property name="itemSearchBean" ref="itemSearchBean"/>
<property name="popupBean" ref="popupBean"/>
</bean>
<!-- Report Bean -->
<bean id="reportGenerationBean" class="com.webapp.service.report.ReportGenerationBean" scope="request">
<property name="itemSearchBean" ref="itemSearchBean"/>
<property name="packingListBean" ref="packingListBean"/>
<property name="scheduleBean" ref="scheduleBean"/>
</bean>
<!-- popupBean -->
<bean id="popupBean" class="com.webapp.service.common.PopupControlBean" scope="session">
</bean>
<!-- JSF backing bean END -->
</beans>

Spring 3 + MyBatis 3

How to create multiple connection databases in spring 3 and mybatis 3. I need to connect to MySQL and Oracle at once.
Can you help me?
You need 1 SqlSessionFactory per database.
<bean id="db1SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:sqlmap1.xml"/>
<property name="dataSource" ref="db1datasource"/>
</bean>
<bean id="db2SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:sqlmap2.xml"/>
<property name="dataSource" ref="db2datasource"/>
</bean>
<bean id="db1SqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<qualifier value="db1" />
<constructor-arg index="0" ref="db1SqlSessionFactory" />
</bean>
<bean id="db2SqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<qualifier value="db2" />
<constructor-arg index="0" ref="db2SqlSessionFactory" />
</bean>

Categories

Resources