Init Custom inner object using spring bean xml - java

I have this kind of class:
Class Food
int type
String name
Class Dog
String dogName
Food food
I want to Init the Dog class using Spring properties, I have no problem to init the dogName value by doing this:
<bean id="dog" class="....Dog">
<property name="dogName" value="dog"/>
...
</bean>
How to set a value for the Food Object?

Use the ref in to refer to the bean id of the food.
<bean id="food" class="....Food"></bean>
<bean id="dog" class="....Dog">
<property name="dogName" value="dog"/>
<property name="food" ref="food"/>
</bean>
<bean id="dog" class="c...dog">
<property name="dogName" value="dog"/>
<property name="food" >
<bean class="...food">
<property name="type" value="1"/>
<property name="name" value="chicken"/>
</bean>
</property>
</bean>
and in case of inner but you can't use it outside of the parent bean tag
<bean id="dog" class="c...dog">
<property name="dogName" value="dog"/>
<property name="food" >
<bean class="...food">
<property name="type" value="1"/>
<property name="name" value="chicken"/>
</bean>
</property>
</bean>

<property name="food">
<bean class="...Food">
<property name="type" value="1"/>
<property name="name" value="Apple"/>
</bean>
</property>
See Spring 3.3.2.3. Inner beans:
A element inside the or elements is used to define a so-called inner bean. An inner bean definition does not need to have any id or name defined, and it is best not to even specify any id or name value because the id or name value simply will be ignored by the container.
<bean id="outer" class="...">
<!-- instead of using a reference to a target bean, simply define the target bean inline -->
<property name="target">
<bean class="com.example.Person"> <!-- this is the inner bean -->
<property name="name" value="Fiona Apple"/>
<property name="age" value="25"/>
</bean>
</property>
</bean>

Use the ref in <property> to refer to the bean id of the food.
<bean id="food" class="....Food">
</bean>
<bean id="dog" class="....Dog">
<property name="dogName" value="dog"/>
<property name="food" ref="food"/>
</bean>

Related

spring bean: good XML data structure for many classes?

I am working on a demo with Java Spring Bean. I have a structure in the applicationContext.xml. Something like that:
<bean id="Transfer1" class="bank.Transfer">
<property name="id" value="1" />
<property name="firstname" value="Thomas" />
<property name="lastname" value="Bäcker" />
<property name="transferdate" value="2016-11-15" />
<property name="amount" value="300" />
</bean>
<bean id="Transfer2" class="bank.Transfer">
<property name="id" value="2" />
<property name="firstname" value="Bob" />
<property name="lastname" value="Sapp" />
<property name="transferdate" value="2016-12-01" />
<property name="amount" value="2700" />
</bean>
//
// followed by Transfer3, Transfer4...
//
I am wondering if there is a better solution, data structure for this. May be something where i can put all Transfers in one Bean instead a long list of Beans. Thx for any advice!
Actually you do not have many classes. You have many instances of the same class...
There is nothing bad with what you done, just because you need 8 instances of the same class with different values only for demo.
If you'd like to combine them into one "holder" bean as collection (array, list, set, map...) you can create your own class (i.e. bank.AllTransfers) with property as any collections (array, list,set,map) and define another bean like
<bean id="allTransfers" class="bank.AllTransfers">
<property name="transfersCollection">
<list>
<ref bean="Transfer1"/>
<ref bean="Transfer2"/>
</list>
</property>
</bean>
Also take a look at Spring Util package (namespace is http://www.springframework.org/schema/util). there are bunch of elements to do the same without another wrapper bean like:
<util:list name="transfersList" list-class="java.util.ArrayList" value-type="bank.Transfer">
<ref bean="Transfer1">
<ref bean="Transfer2">
</util:list>
In that case you will have just a bean of class java.util.ArrayList you can reference to from another beans i.e.
<bean id="allTransfers" class="bank.AllTransfers">
<property name="transfersCollection">
<ref bean="transfersList"/>
</property>
</bean>
for those examples you have to keep your 8 beans definitions "as is".
Of course you can put them right in your list like:
<bean id="allTransfers" class="bank.AllTransfers">
<property name="transfersCollection">
<list>
<bean id="Transfer1" class="bank.Transfer">
<property name="id" value="1" />
<property name="firstname" value="Thomas" />
...
</bean>
<bean id="Transfer2" class="bank.Transfer">
<property name="id" value="2" />
<property name="firstname" value="Bob" />
...
</bean>
</list>
</property>
</bean>
there are many-many possibilities...
PS. but if you still want to keep your 8 beans construction in the Spring context (not from DB, external .properties file ...) you have to have them defined anyway.

Referencing a property of the current bean in Spring EL

I'd like to create a number of beans from a single class, all to be instantiated in the current application context, each based on prefixed properties in a properties file. I've given an example of what I'm trying to achieve. Any tips on how to do this without excessive code (e.g. without multiple classes, complicated factories, etc.) would be appreciated.
XML configuration:
<bean id="bean1" class="Mybean">
<property name="prefix" value="bean1"/>
</bean>
<bean id="bean2" class="Mybean">
<property name="prefix" value="bean2"/>
</bean>
<bean id="bean3" class="Mybean">
<property name="prefix" value="bean3"/>
</bean>
Properties File:
bean1.name=alfred
bean2.name=bobby
bean3.name=charlie
Class:
class Mybean {
#Value("${#{prefix}.name}")
String name;
}
Main Class:
public class Main {
#Autowired
List<MyBean> mybeans;
}
You can use PropertyPlaceholderConfigurer to set bean's name directly (instead of storing its prefix):
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="app.properties"/>
</bean>
<bean id="bean1" class="Mybean">
<property name="name" value="${bean1.name}"/>
</bean>
<bean id="bean2" class="Mybean">
<property name="name" value="${bean2.name}"/>
</bean>
<bean id="bean3" class="Mybean">
<property name="name" value="${bean3.name}"/>
</bean>

Spring+Hibernate+java :Connecting to multiple database after running application

If application is running and connected to Database-1. Through application I want to copy certain data from one Database (it can be Database-1 on any other) to another database. There can be 3-4 database. And schema is exactly same for all the database. Is it possible to do so?
I have read about "AbstractRoutingDataSource" here. But I don't wan't to connect to database during runtime. It should be after runtime.
my spring-config.xml contains bean for JdbcTemplate
<bean id="EnvJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="envDataSource" />
</property>
</bean>
I have created bean for envDataSource (database 1)
<bean id="envDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"/>
<property name="url"/>
<property name="username"/>
<property name="password"/>
</bean>
Seems like you just need to create more beans, and inject them where needed, and call them when you need. This isn't that smart, but you don't need over engineer this.
<bean id="envDataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"/>
<property name="url"/>
<property name="username"/>
<property name="password"/>
</bean>
<bean id="envDataSource2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"/>
<property name="url"/>
<property name="username"/>
<property name="password"/>
</bean>
<bean id="EnvJdbcTemplate1" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="envDataSource1" />
</property>
</bean>
<bean id="EnvJdbcTemplate2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="envDataSource2" />
</property>
</bean>
There is a built in feature in Hibernate to support multiple schemas/databases. find it here

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 Spring IOC overriding property of bean

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>

Categories

Resources