context:property-placeholder doesn't resolve references - spring

I have next applicationContext.xml file on the root of classpath:
<context:annotation-config />
<context:property-placeholder location="classpath:props/datasource.properties" />
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource"
p:username="${jdbc.username}"
p:password="${jdbc.password}"
p:url="${jdbc.url}"
p:driverClassName="${jdbc.driverclass}"
p:validationQuery="SELECT sysdate FROM dual" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="datasource"
p:mapperLocations="classpath:mappers/*-mapper.xml" />
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="datasource" />
<bean id="mappeScannerConfigurere" class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactory-ref="sqlSessionFactory"
p:basePackage="com.mypackage" />
props/datasource.properties also exists on the root of classpath with such content:
jdbc.url=myjdbcurl
jdbc.driverclass=myClass
jdbc.username=myUserName
jdbc.password=myPassword
I have a spring managed test where I declare to use previously mentioned applicationContext.xml via next annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"})
When I invoke test method i get next error from spring:
org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driverclass}'
As I understand sping didn't resolve reference to jdbc.driverclass.
What have I done wrong?
PS: I'm using spring 3.2.3.RELEASE
**
EDIT
**
Perhaps the problem may be in MapperScannerConfigurer. It is a BeanDefinitionRegistryPostProcessor and as Javadoc says:
Extension to the standard BeanFactoryPostProcessor SPI,
allowing for the registration of further bean definitions
before regular BeanFactoryPostProcessor detection kicks in
So MapperScannerConfigurer instantiates datasource object via sqlSessionFactory with BeanFacoryPostProcessor(which is responsible for <context:property-placeholder/>) have not been utilized.
So my question transforms to how to reorder BeanFacoryPostProcessor from <context:property-placeholder/> and BeanDefinitionRegistryPostProcessor(MapperScannerConfigurer)?
Resolved
After a couple hours of investigation I found the solution:
As I said earlier MapperScannerConfigurer is a BeanDefinitionRegistryPostProcessor which fires before BeanFactoryPostProcessor which is responsible for <context:property-placeholder/>. So, during the creation of MapperScannerConfigurer references to external properties will not be resolved. In this case we have to defer the creation of datasource to the time after BeanFactoryPostProcessorhave been applied. We can do that in several ways:
remove p:sqlSessionFactory-ref="sqlSessionFactory" from MapperScannerConfigurer. In this case datasource object will not be created before MapperScannerConfigurer, but after BeanFactoryPostProcessor which is responsible for <context:property-placeholder/>. If you have more than one sqlSessionFactory in applicationContext, than can be some troubles
In versions of mybatis-spring module higher than 1.0.2 there is a possibility to set sqlSessionFactoryBeanName instead of sqlSessionFactory. It helps to resolve PropertyPlaceHolder issue with BeanFactoryPostProcessor. It is a recommended way to solve this issue described in mybatis-spring doc

I was having the same issue and came across this post but I was unable to resolve it the same way maks did. What ended up working for me was to set the ignoreUnresolvablePlaceholders property value to true.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
I am using Spring 3.2.3.RELEASE as well. I realize this post is over 4 months old but I figured someone might find it useful.

Short form: What is the proper way to load an implementation of: BeanDefinitionRegistryPostProcessor?
Expanded form: Is there a way to load BeanDefinitionRegistryPostProcessor before any beans have been created. If you look at the javadoc:
Extension to the standard {#link BeanFactoryPostProcessor} SPI, allowing for
the registration of further bean definitions before regular
BeanFactoryPostProcessor detection kicks in.
So it's meant to be loaded when bean definitions have been created but before any beans have been created. If we just create it as a regular bean in the application xml then it defeats the purpose of having this bean in the first place.

Related

Xml configuration for JdbcChannelMessageStore in a Spring Boot project with Spring Data JPA

I am very new to Spring Integration and would like to use a queue channel which is backed by a JdbcChannelMessageStore.
As our project uses Spring Boot with Spring Data JPA, I would like to have an integration-context.xml configuration where the existing data base connection is reused. However I struggle to make it work.
Unfortunately I cannot find any example projects where JdbcChannelMessageStore is used. Could anyone provide some good example implementations for this?
Thanks a lot in advance.
P.S.: Here is my last integration-context.xml version:
<?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:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="outgoingChannel">
<int:queue message-store="outgoingMessageChannelStore"/>
</int:channel>
<bean id="dp"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${spring.datasource.password}" />
<property name="username" value="${spring.datasource.username}" />
<property name="password" value="${spring.datasource.password}" />
</bean>
<bean id="outgoingMessageChannelStore" class="org.springframework.integration.jdbc.store.JdbcChannelMessageStore">
<property name="dataSource" ref="dp"/>
<property name="channelMessageStoreQueryProvider" ref="jdbcChannelMessageStoreQueryProvider"/>
<property name="region" value="TX_TIMEOUT"/>
<property name="usingIdCache" value="true"/>
</bean>
<bean id="jdbcChannelMessageStoreQueryProvider" class="org.springframework.integration.jdbc.store.channel.OracleChannelMessageStoreQueryProvider" />
<int:transaction-synchronization-factory id="jdbcChannelMessageStoreFactory">
<int:after-commit expression="#jdbcChannelMessageStore.removeFromIdCache(headers.id.toString())" />
<int:after-rollback expression="#jdbcChannelMessageStore.removeFromIdCache(headers.id.toString())" />
</int:transaction-synchronization-factory>
</beans>
With this I am getting the following Exception at startup:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
...
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
Well, since you say that you also use Spring Boot, you probably miss the fact that it auto-configure a DataSource bean for us. Having that dp bean in your config it just neglects that auto-configuration and tries to apply it everywhere you need DataSource, like that Hibernate auto-configuration.
What you really need is exactly opposite - you need to reuse an auto-configured DataSource for this Spring Integration config. Of course, if your JdbcChannelMessageStore is going to rely on the same data base as menitoned Spring Data JPA.
So, what you need is just remove that dp bean definition and use a dataSource name for the <property name="dataSource" in the outgoingMessageChannelStore bean definition.
Some remarks:
We don't need usingIdCache with Oracle and therefore no need in that jdbcChannelMessageStoreFactory to deal with the cache. And that even covered in JavaDocs:
* <p>If using the provided
* {#link org.springframework.integration.jdbc.store.channel.OracleChannelMessageStoreQueryProvider},
* don't set {#link #usingIdCache}
* to true, as the Oracle query will ignore locked rows.</p>
Try to configure Spring Integration with Java & Annotation Configuration (or even Java DSL). This way you won't be tied with a bean name (like that dataSource) and just will have a bean method argument injection for plain DataSource type and Spring container will inject for you an auto-configured bean.

Setting property reference for a bean programmatically

Right now i am using the following bean entry
<bean id="Service" >
<property name="target">
<bean class="someClass" lazy-init="false">
<property name="SessionFactory1"><ref bean="SessionFactory1"/></property>
<property name="SessionFactory2"><ref bean="SessionFactory2"/></property>
<property name="SessionFactory3"><ref bean="SessionFactory3"/></property>
</bean>
</property>
</bean>
Now the requirement is to first check which all session factories have an active datasource and include those only in the above bean definition. So that the application does not break if we try to initialize a session factory with inactive datasource.
sessionfactory initialization will be take care by using seperate config xml for session factories and loading only the ones with active datasources.
Please help on how can this be achieved.
You can use Spring InitializingBean interface, which makes you implement an afterPropertiesSet() method. This method will be executed after Spring instantiates your class, and you could check if your session factories are available or not.
InitializingBean: Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: for example, to perform custom initialization, or merely to check that all mandatory properties have been set.
link: Spring InitializingBean

Spring, XML beans call Annotation beans when app start

I have one Annotation bean with some methods. It works fine.
public #Controller("adminController") class AdminController {
...
private #Autowired AdminDAO adminDAO;
public void resetTemporalList() {
System.out.println("HE SIDO EJECUTADO.");
this.adminDAO.resetTemporalRegisters();
}
...
}
Now, I am integrating one quartz task. But I am load it with XML definition beans that call previus annotation bean.
<bean id="resetTemporalRegisters" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="adminController" />
<property name="targetMethod" value="resetTemporalList" />
<property name="concurrent" value="false" />
</bean>
Whan I start my app appear next error.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'adminController' is defined
I believe the problem is that Spring load XML beans first, after Annotation beans, then in this moment "adminController" bean not exits...
How Can I fix it?
SOLVED IT!!
Problem was in I put xml bean definitions in applicationContext.xml.
No, XML and annotations integrate fine, but do you actually have the component scanning code in your XML?
<context:component-scan base-package="com.yourcompany.yourapp"/>
See: 4.10 Classpath scanning and managed components
A little bit of guessing: your controller is defined in child application context created by Spring MVC while you resetTemporalRegisters job in main application context (parent). Child context can access beans from parent context but not the other way around.
This raises important question: why is your business logic trying to call a method of a controller? These methods should be called only be the MVC framework. Can't you just call
this.adminDAO.resetTemporalRegisters();
directly from your job?
<bean id="resetTemporalRegisters" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="adminDAO" />
<property name="targetMethod" value="resetTemporalRegisters" />
<property name="concurrent" value="false" />
</bean>
adminDAO is probably defined in parent context, so you can access it easily.

Why is autowiring required? What is the explanation of the concept of autowiring?

Why is autowiring required? What is the explanation for the concept of autowiring?
#autowired annotation in Spring Framework.
Autowiring is not required, just convenient.
It means that if you have a property that requires an InterfaceA and a single bean has been declared in Spring that is of type InterfaceA, instead of using XML to manually "wire up" the relationship (setting a bean reference as a property of another), you can let Spring do the wiring for you.
This is a common question for the beginners. As the beans are injected using DI (setter injections, constructor injections), why do we need auto-wiring? Auto-wiring also doing the same thing, right?
The answer is, it saves you from writing more code.
If using an XML file, using autowire attribute saves you from writing the wiring code in the bean definition.
Please look at code below.
Configuration code without Auto-wiring:
<bean id="employee" class="com.Employee">
<property name="name" value="Dexter"></property>
</bean>
<bean id="employeeService" class="com.EmployeeService">
<property name="employee" ref="employee"></property>
</bean>
Configuration code with Auto-wiring:
<bean id="employee" class="com.Employee">
<property name="name" value="Dexter"></property>
</bean>
<bean id="employeeService" class="com.EmployeeService" autowire="byName" />
Note that we did not have to write anything to refer property of EmployeeService, i.e., Employee. But still it was injected. Autowiring makes the container to search the bean configurations and do the collaboration among beans, without the developer specifically mentioning these.
If we use annotation, even we don’t have to write anything in XML files, including this autoware="byName", etc. Simply #Autowired on bean's setter/field/constructor is sufficient.

Configuring Datasource in Spring 3.0

Hello guys I have configured a connection pool and JNDI resource in glassfish 2.1. I can get the Datasource via lookup method in my projects and everything works good. However I decided to try Spring framework and to use my existing connection pool.
In the Spring context file I have the following:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/name" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="dao" class="com.mycompany.mavenproject3.Dao">
<property name="simpleJdbcTemplate" ref="jdbcTemplate"/>
</bean>
When I deploy the project I get:
java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required]
Is there anything else I have to configure in that file or in any other file in order to get the Datasource?
Presumably, com.mycompany.mavenproject3.Dao extends JdbcDaoSupport, but you're setting a property named simpleJdbcTemplate on it, leading me to believe that you've defined your own property to hold the template since that doesn't exist on Spring's implementation. It's therefore complaining at you because you're required to set either the dataSource property or the jdbcTemplate property of the JdbcDaoSupport object before using it, exactly like it's telling you. Change <property name="simpleJdbcTemplate"... to <property name="jdbcTemplate"....
If your DAO doesn't extend JdbcDaoSupport, then find what does and remove it or set its properties appropriately.
You can also call your datasource directly in your dao bean, don't need to do an another bean for jdbcTemplate. So your context file become something like this:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/name" />
<bean id="dao" class="com.mycompany.mavenproject3.Dao">
<property name="dataSource" ref="dataSource"/>
</bean>
After you just have to extends JdbcDaoSupport spring class (in which contain the getter and setter of datasource) on your Dao class.

Resources