Dynamic serviceUrl with Spring’s HttpInvokerProxyFactoryBean
Abstract
How to set dynamically the URL used by a HttpInvokerProxyFactoryBean
in a Spring-deployed WAR?
Detailed Case
I have to deploy a GWT/GXT application, calling two distant services:
a remote EJB
a service accessed through Spring Remoting
Here is the Spring configuration file I firstly used:
[xml]
<util:properties id="jndiProperties" location="classpath:jndi.properties"/>
<jee:remote-slsb id="myRemoteEJBService" jndi-name="ejb.remote.myRemoteService"
business-interface="lalou.jonathan.myRemoteEJBService"
environment-ref="jndiProperties" cache-home="false"
lookup-home-on-startup="false" refresh-home-on-connect-failure="true" />
<bean id="mySpringRemoteService"
class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceInterface"
value="lalou.jonathan.services.mySpringRemoteService" />
<property name="serviceUrl" value="${spring.remote.service.url}"/>
</bean>
[/xml]
Unhappily, even though the remote EJB is retrieved (which proves that the jndi file is available in the classpath and rightly loaded), the Spring Remote service is not. I had to write the URL in hard in the configuration file… This is not very efficient when you work in a large team, with different production and testings environments!
This is the log when myRemoteEJBService
bean is loaded:
[java]2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory – Creating shared instance of singleton bean ‘myRemoteEJBService’
2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory – Creating instance of bean ‘myRemoteEJBService’
2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory – Eagerly caching bean ‘myRemoteEJBService’ to allow for resolving potential circular references
2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory – Returning cached instance of singleton bean ‘jndiProperties’
2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory – Invoking afterPropertiesSet() on bean with name ‘myRemoteEJBService’
2010-08-17 16:05:42,937 DEBUG framework.JdkDynamicAopProxy – Creating JDK dynamic proxy: target source is EmptyTargetSource: no target class, static
2010-08-17 16:05:42,953 DEBUG support.DefaultListableBeanFactory – Finished creating instance of bean ‘myRemoteEJBService'[/java]
That is the log when mySpringRemoteService
is loaded:
[java]2010-08-17 16:05:42,968 DEBUG support.DefaultListableBeanFactory – Creating shared instance of singleton bean ‘mySpringRemoteService’
2010-08-17 16:05:42,968 DEBUG support.DefaultListableBeanFactory – Creating instance of bean ‘mySpringRemoteService’
2010-08-17 16:05:42,984 DEBUG support.DefaultListableBeanFactory – Eagerly caching bean ‘mySpringRemoteService’ to allow for resolving potential circular references
2010-08-17 16:05:43,234 DEBUG support.DefaultListableBeanFactory – Invoking afterPropertiesSet() on bean with name ‘mySpringRemoteService’
2010-08-17 16:05:43,250 DEBUG framework.JdkDynamicAopProxy – Creating JDK dynamic proxy: target source is EmptyTargetSource: no target class, static
2010-08-17 16:05:43,250 DEBUG support.DefaultListableBeanFactory – Finished creating instance of bean ‘mySpringRemoteService'[/java]
You can notice that no mention to jndiProperties
appears. Here is the key of the problem: jndiProperties
is considered as a bean among others, which cannot be accessed easyly from the HttpInvokerProxyFactoryBean
.
Fix
To fix the issue, you have to add an actual property holder in Spring XML configuration file, ie after:
[xml]<util:properties id="jndiProperties" location="classpath:jndi.properties"/>[/xml]
add an instanciation of PropertyPlaceholderConfigurer
:
[xml]<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jndi.properties"/>
</bean>[/xml]