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.
Related
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.
I'm trying to create a MarshallingMessageConverter, here is my XML:
<bean id="marshallingMessageConverter" class="org.springframework.jms.support.converter.MarshallingMessageConverter">
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="marshaller" />
<property name="marshalTo" value="MARSHAL_TO_TEXT_MESSAGE" />
</bean>
I am getting the following error:
Error setting property values; nested exception is
org.springframework.beans.NotWritablePropertyException:
Invalid property 'marshalTo' of bean class
[org.springframework.jms.support.converter.MarshallingMessageConverter]:
Bean property 'marshalTo' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
Is this because MarshallingMessageConverter doesn't have a getMarshalTo method, and so setting it in this way isn't working?
It looks like it should be possible, as I found https://jira.spring.io/browse/SWS-614, and someone else said they have the following config working:
<bean id="marshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
<bean id="xstream" class="org.springframework.oxm.support.MarshallingMessageConverter"
p:marshaller-ref="marshaller" p:unmarshaller-ref="marshaller" p:marshalTo="2"/>
<!--marshalTo=2 sets the marshaller to text message rather than bytes message-->
So I feel like maybe it's something I'm missing. I've tried using an int in the value, but that doesn't work either.
I want to use XML config because I'm using Spring Integration, and don't want to be pulling beans out of the app-context using Java.
I am using Spring version 3.2.1.RELEASE.
I was missing something... I was looking at the documentation for
org.springframework.oxm.support.MarshallingMessageConverter
but the one that I was using was
org.springframework.jms.support.converter.MarshallingMessageConverter
which has the method, toTargetType().
Not sure if I should delete my question or leave it here in case someone else does the same thing.
<bean id="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor"
class="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor">
<property name="worksiteManager">
<ref bean="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager"/>
</property>
</bean>
I am injecting ref bean from a jar file..
Exception is:
Cannot resolve reference to bean 'org.sakaiproject.metaobj.worksite.mgt.WorksiteManager' while setting bean property 'worksiteManager';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.sakaiproject.metaobj.worksite.mgt.WorksiteManager' is defined
You must add a
<bean id="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager" class="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager"/>
in your application context.
Bean id and class name are not the same thing, even if you're giving them the same value.
The bean id should be a "handy" name you use to refer to a bean isntance, while the class is the actual fully qualified class name to load the bean from the classpath (jar or your class folder or whatever).
do like that, give a bean id, and then call the reference by calling that id.
<bean id="Order" class="com.classes.OrderPizza">
<property name="pizzaTemp" ref="ChickenPizza"></property>
</bean>
<bean id="ChickenPizza" class="com.classes.ChickenPizza"></bean>
<bean id="PaneerPizza" class="com.classes.PaneerPizza"></bean>
The problem is that you are referencing a bean without instantiating it. Correct your code this way:
<bean id="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor" class="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor">
<property name="worksiteManager">
<bean class="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager"/>
</property>
</bean>
NOTE You also have to be sure the jar is deployed in your project binaries.
<context:property-placeholder
location="a.properties,b.properties"
ignore-unresolvable="true"/>
result: both properties file are loaded
<context:property-placeholder
location="${properties_location}"
ignore-unresolvable="true"/>
where properties_location is "a.properties,b.properties"
result: Exception in thread "main" org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: class path resource [a.properties,b.properties] cannot be opened because it does not exist
edit: ${properties_location} is set the following way:
System.getProperties().setProperty("properties_location", "a.properties,b.properties");
ApplicationContext ctx = new GenericXmlApplicationContext("context.xml");
...
How can I initialize my application the 2nd way? to have all the properties file's path defined in a placeholder.
You have to change this to:
<context:property-placeholder
location="classpath:a.properties,
classpath:b.properties"
ignore-unresolvable="true"/>
From the source of the parser for the property-placeholder element.
String location = element.getAttribute("location");
if (StringUtils.hasLength(location)) {
String[] locations = StringUtils.commaDelimitedListToStringArray(location);
builder.addPropertyValue("locations", locations);
}
First the location is retrieved, if that has a value it is converted to a String[]. Springs conversion service takes care of replacing any placeholders in the String[]. But at that moment the properties_location placeholder is just a single element in the array and that gets resolved to a.properties,b.properties without further processing.
So at the moment this isn't possible with placeholders I'm afraid.
One thing that might work is using SpEL if it is always going to be a system property you can use #{systemProperties['properties_location']} to resolve the value. That should be resolved before anything else.
You cant use a property placeholder as a value in a placeholder placeholder resolver. Its like saying, "hey, resolve the placeholder for the location of the all the properties, and then you can start resolving properties!".
Logically it just dosent make sense. I was experimenting with spring property placeholder resolution recently, and stumbled upon this same question. I attempted to use two property placeholder configurers, one to resolve the location of the properties for the second, and the second to resolve the rest of the properties. Of course this dosent work due to the way in which spring initialises its beans.
Initialise bean post processors
Construct them
Construct all other beans
Since the property placeholder configurer is a bean post processor, if you have more than one of them, they get initialised and constructed at the same time, so know nothing of each others properties at construction
Edit
Given that the property location is a system property you could have:
System.getProperties().setProperty("properties_location_a", "classpath:/a.properties");
System.getProperties().setProperty("properties_location_b", "classpath:/b.properties");
And then in your spring content.xml:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>${properties_location_a}</value>
<value>${properties_location_b}</value>
</list>
</property>
</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.