I have legacy project with a lot of beans in several contexts. Seems like there are circular dependencies between beans and that's why most of contexts has default-lazy-init set to true.
I need export some bean via RMI, so I have folowing declarations in the context:
<bean id="partnershipPluginService" class="com.otr.sufd.services.security.PartnershipPluginServiceImpl" lazy-init="false">
<property name="selectionService" ref="selectionService"/>
<property name="editObjectService" ref="editObjectService"/>
<property name="securityFieldsService" ref="securityFieldsService"/>
<property name="cryptoSettingsService" ref="cryptoSettingsService"/>
<property name="authenticationService" ref="systemAuthenticationService"/>
<property name="configurationManager" ref="serverConfigurationManager"/>
<property name="lifeCycleDefService" ref="lifeCycleDefService"/>
</bean>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter" depends-on="partnershipPluginService" lazy-init="false">
<property name="registryPort" value="${rmi.port}"/>
<property name="serviceName" value="partnershipPluginService"/>
<property name="serviceInterface" value="com.otr.security.synchronization.service.PartnershipPluginService"/>
<property name="service" ref="partnershipPluginService"/>
</bean>
Both this beans declared as not lazy. I thibk, enough declare at least one RmiServiceExporter as non lazy to have the same behavior.
In this configuration there are one big disadvantage. It doesn't work. I have exception in context creation process
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'partnershipSystemPluginService' defined in
class path resource
[security/serverSecurityServices.xml]: Cannot
resolve reference to bean 'cryptoSettingsService' while setting bean
property 'cryptoSettingsService'; nested exception is
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'cryptoSettingsService': Bean with name
'cryptoSettingsService' has been injected into other beans
[jinnCryptoService,jinnCryptoServerService] in its raw version as part
of a circular reference, but has eventually been wrapped. This means
that said other beans do not use the final version of the bean. This
is often the result of over-eager type matching - consider using
'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for
example.
At first look, there is no circular dependency between jinnCryptoService and jinnCryptoServerService. If I make both RmiServiceExporter and partnershipPluginService lazy like others - context creates with no exceptions, but RMI doesn't work.
So, is any way to have context and RMI working? Thanks for helping me and wasting your time.
So,I found a solution.
I took a look for context's neighborhood and got a few contexts with beans like RmiServiceExporter. That contexts is not lazy and get started after lazy contexts with beans like partnershipPluginService.
I replaced RmiServiceExporter into new context and the problem is solved.
If you'll be in my place, please take a few looks on the problem from different angles and you find an answer.
Thanks to all, who read this post, trying to help me.
Related
I have the following construct Spring XML (Spring 3.1):
<bean id="taskRunner" abstract="true" init-method="startThreads"
class="my.class.TaskRunner" />
...
<bean id="taskRunnerA" parent="taskRunner">
<constructor-arg name="foo">...</constructor-arg>
<property name="bar">...</property>
</bean>
And I am trying to separate out the init method into a higher level abstract bean:
<bean id="taskRunnerLauncher" abstract="true" init-method="startThreads" />
<bean id="taskRunner" abstract="true" depends-on="taskRunnerLauncher"
class="my.class.TaskRunner" />
...
<bean id="taskRunnerA" parent="taskRunner">
<constructor-arg name="foo">...</constructor-arg>
<property name="bar">...</property>
</bean>
Somehow this does not work, i.e. startThreads() is never invoked in the second case. Does anybody know why? Does Spring support nested abstract beans?
My idea for doing this is so I can override "taskRunnerLauncher" in unit tests and set it to "mock" or "java.lang.Object" and suppress startThreads() call (which starts new thread and making it a pain to test).
Does anybody know why?
The taskRunnerLauncher bean is set to be abstract. This means it will only act as a template for other beans. Spring will not actually create a bean for it. Therefore there won't be any invocation of startThreads because there is nothing to invoke it on.
Found the problem. I mistakenly used depends-on instead of parent attribute on taskRunner bean.
I have a spring xml file with some beans, two of which I have pasted below:
<bean
class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
<property name="locations">
<value>classpath:projectname-override.properties</value>
</property>
</bean>
<bean id="myBeanName"
class="my.company.department.svc.spring.WmSvcJndiDataSource">
<property name="jndiName">
<value>jdbc/XXXXX</value>
</property>
<property name="jndiTemplate">
<ref bean="myJndiTemplate" />
</property>
</bean>
The properties file referred to in the first bean is very small (currently only one line), and looks like this:
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV3
It is my understanding that PropertyOverrideConfigurer in the first bean
pushes values from a properties file into bean definitions
So the value of the jndiName property in the myBeanName bean will turn from
jdbc/XXXXX
to
java:comp/env/jdbc/XXXXX_YYY_DEV3.
This works and it partially does what we want. I need to expand the functionality so that I can handle multiple deployment environments. This currently replaces the bean property for one of our development environments (dev3). I think I need spring to dynamically alter "myBeanName" for about 25 different dev environments.
For example, I think I want my properties file to look like this
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV1
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV2
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV3
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV4
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV5
...
...
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV24
myBeanName.jndiName=java:comp/env/jdbc/XXXXX_YYY_DEV25
I have no idea if this is the right approach.
Any ideas?
Thanks in advance.
NOTE
my.company.department.svc.spring.WmSvcJndiDataSource in the second bean is simply a class we extended off of org.springframework.jndi.JndiObjectFactoryBean, FYI. I don't know if that is important to know or not.
I have a problem with the followingspring context configuration file:
...
<context:property-override location="classpath:query_1.properties" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:query_2.properties" />
</bean>
....
The problem is that the properties in the file "query_2.properties" cannot be found. The exception I get ist he following one:
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException. Could not resolve placeholder...
Now my question: is it possible that the combination of context:property-override and PropertyPlaceholderConfigurer does make no sense? Can anyone explain me in simple words what is the difference between both? Any help would be appreciated.
Thx. Horace
Property placeholders, normally defined using a <context:property-placeholder location=../> resolves the placeholders in bean definitions:
for eg.
<bean name="myclass" class="MyClass">
<property name="prop1" value="${prop1val}/>
</bean>
if the location specified with property placeholder has a property with name prop1val:
prop1val=aval
then it will be replaced in the bean myclass.
PrpertyOverrideConfigurer defined using <context:property-override location="classpath:query_1.properties" /> on the other is like a push mechanism, the property is of the form beanname.property and it would push this property into the bean with name beanname.
For eg. for the above case if the location had a property of:
myclass.prop1=aval
then it would inject in prop1 of myclass bean
The exception you are getting simply indicates that it is not able to find query_2.properties file, I doubt if it is any other configuration issue.
On which one will take effect if both are defined, I think the last one will the one to take effect.
I am exposing a bean that is not thread safe via Spring's http invoker. What I want is that every remote call should get a new instance of the bean. I started by setting the scope to prototype for the bean that I am exposing in the Dispatcher servlet XML. But it still seemed to create only one instance. So all client threads were concurrently accessing the same bean instance.
Next I also set the scopr to prototype for HttpInvokerProxyFactoryBean in the client spring-config.xml. But even then I see a single instance of the bean being returned.
Any ideas on what I am doing wrong? Or has anyone else faced this problem.
Thanks in advance.
Here are the relevant snippets
DispatcherServlet-servlet.xml
<bean id="fuBeanImpl" class="com.fubar.FuBeanImpl" scope="prototype">
</bean>
<bean id="fuBeanService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="fuBeanImpl"/>
<property name="serviceInterface" value="com.fubar.FuBean"/>
</bean>
spring-config.xml
<bean id="fuBeanService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean" scope="prototype">
<property name="serviceUrl">
<value>http://fubar/fuBeanService</value>
</property>
<property name="serviceInterface">
<value>com.fubar.FuBean</value>
</property>
<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
</property>
</bean>
There is another current question Prototype Scope not working about an almost identical problem.
Both of these solutions should work here also:
Tight coupling to the
ApplicationContext and looking up the
Bean manually
Lookup Method Injection via
CGLib (by yours truly)
This is because your HttpInvokerServiceExporter bean is still a singleton, and it has a reference to the prototype-scoped fuBeanImpl bean. So the exporter gets a single instance of FuBeanImpl and never asks for a new one. This is the problem with singleton-scoped beans referring to on-singleton-scoped beans - the reference "collapses" the prototype, effectively.
You need to make HttpInvokerServiceExporter a prototype-scoped bean also, although this might have side-effects. For example, you haven't told us what is referring to the HttpInvokerServiceExporter - probably a url-mapping definition somewhere?
edit: Since you've clarified that you're using a SimpleUrlhandlerMapping, then what you can do is to inject that with the name of the handler bean, rather than a direct bean reference to it. This means that the handler bean (i.e. the fuBeanService bean) can be a prototype, even though the SimpleUrlhandlerMapping is a singleton.
<bean id="data.emf"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="transactions-optional" />
</bean>
from what i know by default all bean are singleton (according to document) but i somehow still getting duplicated creating of entitymanagerfactory. is there any parameter i can set for bean above in spring 3.0 to force singleton? the problem only appear in gae production, on hosted mode, no problem
You can force a bean to be a singleton like this:
<bean scope="singleton" ... >
</bean>
You generally don't need to do this, however, since singleton is the default scope, and there's no way to change the default.
The Spring DEBUG-level logs will generate entries every time a bean is instantiated, so have a look through there to see when and where your bean is being processed.
Maybe the problem doesn't come form the scope. Are you sure you haven't defined another bean in anther place of the program (for example with an annotation) or in another context file? Comment that bean definition and try if it can find a instance of it without declaring it here.