Использование пространства имен весеннего облака и двух источников данных
У меня есть WAR-компонент Spring Integration, который я обновляю, чтобы запустить в частном PCF. У меня есть два источника данных и фабрика соединений RabbitMQ, определенные в приложении.
Я вижу статью Томаса Рисберга об использовании облачного пространства имен и обработке нескольких служб одновременно - https://spring.io/blog/2011/11/09/using-cloud-foundry-services-with-spring-part-3-the-cloud-namespace. Это выполняется с помощью аннотаций @Autowired и @Qualifier.
Мне интересно, как это может быть достигнуто, хотя, когда мы не аннотации @Autowired и @Qualifier, например, подключаем DataSource к JdbcTemplate. Здесь у нас нет возможности указать аннотацию @Qualifier.
Мое приложение основано на Spring XML config. У меня есть возможность использовать аннотации @Autowired и @Qualifier на одном из источников данных, но другой - диспетчер сущностей JPA. Смотрите фрагмент кода.
Буду признателен за любую оказанную помощь.
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="activity-monitor" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<value>
hibernate.format_sql=true
</value>
</property>
</bean>
<beans profile="cloud">
<cloud:data-source id="dataSource" service-name="actmon-db-service" />
</beans>
Пакет сборки Java: java_buildpack_offline java-buildpack-offline-v2.4.zip Spring Auto-перенастройка версии 1.4.0.
ОБНОВЛЕНИЕ: Это полная конфигурация для обоих источников данных, включая PropertySourcesPlaceholderConfigurer со свойствами, загруженными из источника данных с использованием DAO.
<bean id="cic.application.ppc" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="properties" ref="cic.application.properties"/>
<property name="locations" ref="cic.application.propertyLocations"/>
</bean>
<bean id="cic.application.properties" class="java.util.Properties">
<constructor-arg value="#{cicPropertiesService.properties}"></constructor-arg>
</bean>
<bean id="cic.properties.propertiesService" name="cicPropertiesService"
class="com.emc.it.eis.properties.service.DefaultPropertiesService">
<constructor-arg index="0"
ref="cic.properties.propertiesDao" />
</bean>
<bean id="cic.properties.propertiesDao" class="com.emc.it.eis.properties.dao.JdbcPropertiesDao">
<constructor-arg ref="cic.properties.dataSource" />
</bean>
<beans profile="default">
<jee:jndi-lookup id="cic.properties.dataSource"
jndi-name="jdbc/intdb" />
</beans>
<beans profile="cloud">
<cloud:data-source id="cic.properties.dataSource" service-name="oracle-cicadm-db-service" />
</beans>
<beans>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="actmonDataSource" />
<property name="persistenceUnitName" value="activity-monitor" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<value>
hibernate.format_sql=true
</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
<beans profile="default">
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/actmon" />
</beans>
<beans profile="cloud">
<cloud:data-source id="actmonDataSource" service-name="postgres-actmon-db-service" />
</beans>
<beans profile="default,cloud">
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="POSTGRESQL" />
</bean>
</beans>
Вывод из CF при развертывании https://gist.github.com/anonymous/3986a1a7cea4f20c096e. Обратите внимание, что пропускается автоматическая переконфигурация javax.sql.DataSources
2 ответа
Прежде всего, сообщение от Томаса довольно старое, и в нем упоминается устаревшая библиотека поддержки. Вместо org.cloudfoundry:cloudfoundry-runtime:0.8.1
зависимость, вы должны вместо этого использовать зависимости Spring Cloud Connectors.
Затем вы можете следовать инструкциям по использованию конфигурации XML с Spring Cloud Connectors. С несколькими службами одного типа вам нужно будет указать имя службы для каждого компонента. Следуя вашему примеру и предполагая, что вы создали две службы баз данных CF с именем inventory-db
а также customer-db
, это может выглядеть примерно так:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="inventory-dataSource" />
<property name="persistenceUnitName" value="activity-monitor" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<value>
hibernate.format_sql=true
</value>
</property>
</bean>
<beans profile="cloud">
<cloud:data-source id="inventory-dataSource" service-name="inventory-db">
<cloud:data-source id="customer-dataSource" service-name="customer-db">
</beans>
Мне удалось решить эту проблему с помощью фабричного компонента, используемого весенним облаком: источник данных, CloudDataSourceFactory
, Создание экземпляра этого и подключение конфигурации, включая service-name
услуги CF. Это позволяет избежать проблемы, связанной с попыткой нашего PropertySourcesPlaceholderConfigurer использовать источник данных еще до того, как наш компонент был определен.
<!--
configure cloud data source for using CloudDataSourceFactory; this is what spring cloud:data-source is using;
required to manually wire this data source bean as cloud:data-source bean gets defined in a phase after our
PropertySourcesPlaceholderConfigurer bean.
-->
<bean id="cic.properties.dataSource" class="org.springframework.cloud.service.relational.CloudDataSourceFactory">
<constructor-arg value="oracle-cicadm-db-service" />
<constructor-arg>
<!-- configuring minimal data source as it is used only to bootstrap properties on app start-up -->
<bean class="org.springframework.cloud.service.relational.DataSourceConfig">
<constructor-arg>
<bean class="org.springframework.cloud.service.PooledServiceConnectorConfig.PoolConfig">
<constructor-arg value="0" />
<constructor-arg value="2" />
<constructor-arg value="180" />
</bean>
</constructor-arg>
<!-- ConnectionConfig not required for cic.properties.dataSource so setting to null -->
<constructor-arg value="#{ null }" />
</bean>
</constructor-arg>
</bean>