I'm trying to create a FreeMarker configuration in Spring 4 using org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean, and then customising the resulting freemarker.template.Configuration (to change the arithmetic engine).
I'm using the following XML config (simplified):
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPaths">...</property>
...
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="freemarkerConfiguration" />
<property name="targetMethod" value="setArithmeticEngine" />
<property name="arguments" value="#{T(freemarker.core.ArithmeticEngine).CONSERVATIVE_ENGINE}" />
</bean>
It works, but I get a lot of warnings during the application startup:
2015-02-27 13:53:03,321 [localhost-startStop-1] [:] WARN support.DefaultListableBeanFactory - Bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.beans.factory.config.MethodInvokingFactoryBean#0' defined in ServletContext resource [/WEB-INF/spring/freemarker.xml]: Cannot resolve reference to bean 'freemarkerConfiguration' while setting bean property 'targetObject'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'freemarkerConfiguration': FactoryBean which is currently in creation returned null from getObject
My understanding is that it happens because the FreeMarkerConfigurationFactoryBean implements the FactoryBean<> interface. As such, this FactoryBean is "prepared" first, and then FactoryBean.getObject() is called whenever the actual bean it creates (freemarker.template.Configuration) needs to be accessed.
It seems the MethodInvokingFactoryBean gets invoked while the underlying bean is still being "prepared" by FreeMarkerConfigurationFactoryBean, resulting in FreeMarkerConfigurationFactoryBean.getObject() returning null and the method invocation failing.
I suspect I'm getting a lot of warnings because Spring repeatedly tries to invoke the method and fails. At some point the bean produced by the factory is ready, and the method invocation works.
So:
Is my analysis correct?
Why is that happenning? I would think the dependency injection system should detect the dependency between the MethodInvokingFactoryBean and the freemarkerConfiguration, and invoke the method after the factory bean is ready. I tried to add depends-on="freemarkerConfiguration" on the MethodInvokingFactoryBean but it didn't help.
Is there a way to achieve what I want in XML (I can't switch to Java #Configuration right now). Basically I need a way to call freemarker.core.Configurable.setArithmeticEngine() from XML.
Thanks.
After reading some spec I find this, hope is useful for you:
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerSettings">
<props>
<prop key="arithmetic_engine">conservative</prop>
</props>
</property>
</bean>
ref: Freemarker Docs
A FactoryBean is supposed to create a bean, not to call a method on a bean! Also the method invoking version will try to create a bean by calling the configured method of the object passed to create a new bean.
What you should look on instead, is the freemarkerSettings property of the FreeMarkerConfigurationFactoryBean and set properties including the arithmetic engine:
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPaths">...</property>
<property name="freemarkerSettings">
<map>
<entry key="#{T(freemarker.core.Configurable).ARITHMETIC_ENGINE_KEY}"
value="#{T(freemarker.core.ArithmeticEngine).CONSERVATIVE_ENGINE}"/>
</map>
</property>
...
</bean>
Related
In Spring boot application, Getting below exception when added file:nio-locker in inbound-channel-adapter
to obtain file-locking
Exception : The 'filter' and 'locker' options must be present on the provided external 'scanner'
Stack trace :
facing below error while starting the application.Cannot resolve reference to bean 'filesInChannel.adapter.source' while setting bean property 'source'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'filesInChannel.adapter.source': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: The 'filter' and 'locker' options must be present on the provided external 'scanner': org.springframework.integration.file.RecursiveDirectoryScanner#358ee631
The 'filter' and 'locker' options must be present on the provided external 'scanner
<file:inbound-channel-adapter id="filesInChannel"
directory="file:${base.path}" auto-startup="false" scanner="recursiveScanner" auto-create-directory="true">
<integration:poller id="poller" max-messages-per-poll="${max.messages.per.poll}" fixed-rate="${message.read.frequency}" task-executor="pollingExecutor">
<integration:transactional transaction-manager="transactionManager" />
</integration:poller>
<file:nio-locker/>
</file:inbound-channel-adapter>
<bean id="inboundFilter" class="org.springframework.integration.file.filters.CompositeFileListFilter">
<constructor-arg>
<list>
<bean class="org.springframework.integration.file.filters.AcceptOnceFileListFilter"/>
<bean class="org.springframework.integration.file.filters.RegexPatternFileListFilter">
<constructor-arg value="${file.type}"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean id="recursiveScanner" class="org.springframework.integration.file.RecursiveDirectoryScanner">
<property name="filter" ref="inboundFilter" />
</bean>
could you please suggest on this.
You do scanner="recursiveScanner" on the <file:inbound-channel-adapter>, but at the same time you use <file:nio-locker/> sub-element. That's how you violate a requirements and get that exception.
According a recommendation in the error message you need to move a NioFileLocker reference into the RecursiveDirectoryScanner bean definition instead:
<bean id="recursiveScanner" class="org.springframework.integration.file.RecursiveDirectoryScanner">
<property name="filter" ref="inboundFilter" />
<property name="locker" ref="nioLocker" />
</bean>
I don't have much experience working with Spring Context and I don't know if this is possible...I'm trying to set into a Spring XML file a variable to define a bean reference (not a property).
Now I have a specidific xml:
keyIntegrator-key1.xml
<import resource="classpath:/events/key-events.xml" />
<context:annotation-config />
<bean id="keyIntegrator" class="com.emulated.KeySimulator" >
<property name="readList">
<list>
<bean class="com.emulated.ListEventGenerator">
<property name="eventList">
<ref bean="key-1-ok"/>
</property>
</bean>
</list>
</property>
</bean>
All the keys were defined in another xml file (key-events.xml).
I have to load in Java runtime the bean "keyIntegrator" with only one key, that is a input parameter in the Java program (I use the param to decide the xml file to load)
My question is if it's possible to define a variable inside the xml file and get the referenced bean using this variable:
Something like this:
keyIntegrator-generic.xml
<import resource="classpath:/events/key-events.xml" />
<context:annotation-config />
<bean id="keyIntegrator" class="com.emulated.KeySimulator" >
<property name="readList">
<list>
<bean class="com.emulated.ListEventGenerator">
<property name="eventList">
<ref bean="key-{inputKeyParam}-ok"/>
</property>
</bean>
</list>
</property>
</bean>
In the Java program I will need to pass the param to get the bean, something like this:
keySimulatorBean = (KeySimulator) context.getBean("keyIntegrator", "1");
There any way possible to make this ?
Thank you very much!
Thank you very much, it worked for me :)
I setted the system property value in the Java code:
System.setProperty("inputKeyParam", "1");
It is possible to do using Spring Expression Language.
For example reference to the bean can be defined using system property
<ref bean="key-#{systemProperties.inputKeyParam}-ok"/>
It will allow to reference different beans depending on provided VM option value, e.g. -DinputKeyParam=1
I've come across a little problem concerning the utilization of Configuration classes in bean injection when migrating to Hibernate 4.3.
The configuration class I inject overrides certain methods from the org.hibernate.cfg.Configuration Class like validateSchema()
In Hibernate 3, I have this in my configuration file and it works because the get/set methods for configurationClass exists :
<bean id="SessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="$[DATA_SOURCE]" />
</property>
<property name="entityInterceptor">
<ref bean="entityInterceptor"/>
</property>
<property name="configurationClass">
<value>com.hibernate.cfg.CustomSchemaValidationConfiguration</value>
</property>
Meanwhile, in Hibernate 4.3, I get this error because the setConfigurationClass() method doesn't exist anymore.
Invalid property 'configurationClass' of bean class [org.springframework.orm.hibernate4.LocalSessionFactoryBean]: Bean property 'configurationClass' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
Thing is that I still want/need to use que configuration class.
I've seen many examples in code but I want to stay with the spring injection way. Is it posible ? Any suggestions ?
I have a service which refers to a single source.
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref="DataSource1" />
</bean>
<bean id="DataSource1" class="com.source.impl.DataSource1">
<constructor-arg ref="DBDataSource"/>
<constructor-arg value="xyz"/>
</bean>
<bean id="DataSource2" class="com.source.impl.DataSource2">
<constructor-arg ref="MsgDataSource"/>
<constructor-arg value="xyz"/>
</bean>
Now if i want to perform a conditional check and my service should be able listen to particular source based on a input variable something like below.
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref=" $VARIABLE == true ? DataSource1 : DataSource2" />
</bean>
I did tried SPEL however no luck. I am beginner in spring. Any help will be appreciated.
Thanks.
There are many solutions. Here are two: You can use profiles for this. Define two profiles, define the DataSource beans with the same name but different profiles. (docs)
Alternatively, you can use a single bean and a static factory method (docs).
<bean id="DataSource" class="com.source.impl.DataSourceFactory"
factory-method="createInstance"/>
Inside of DataSourceFactory.createInstance(), you can check the flag and then create the correct data source in plain Java.
The latter is a bit easier to understand, IMO. Using profiles allows you to keep everything in XML (but you should really consider switching to the Java Configuration). The drawback with profiles is that you must not forget to activate at least one of the bean won't be defined.
A third option is to use three XML files and then modify the list of XML files that should be parsed when you pass it to the ApplicationContext. But that only works if you have control over this part of the code.
Assuming you are using Spring 3.1 or later, Spring Profiles may be the best solution.
Using the example of Production and Dev/QA environments, common bean declarations go in a shared file
<beans>
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref="DataSource" />
</bean>
</beans>
A separate configuration contains production references
<beans profiles="prod">
<bean id="DataSource" class="com.source.impl.DataSource1">
<constructor-arg ref="DBDataSource"/>
<constructor-arg value="xyz"/>
</bean>
</beans>
Another contains dev references
<beans profile="dev">
<bean id="DataSource" class="com.source.impl.DataSource2">
<constructor-arg ref="MsgDataSource"/>
<constructor-arg value="xyz"/>
</bean>
</beans>
To activate the given profile add -Dspring.profiles.active=prod to your JVM arguments
You can find more info here
Another approach uses factory methods.
<bean id="DataSource" class="com.source.impl.DataSourceFactory" factory-method="getInstance">
<constructor-arg value="#{VARIABLE}" />
</bean>
The above fragment assumes that you want your factory method to explcitly invoke the constructor of each of your services. If you dead set on using Spring to create the instances you can pass each datasource implementation as constructor arguments and use the constructor method as a simple dispatcher.
You need something like this:
<constructor-arg
ref="#{systemProperties.variable == 'true' ? 'DataSource1' : 'DataSource2'}" />
where "variable" is set like -Dvariable=true.
I have a PropertyPlaceholderConfigurer like this:
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:assuredlabor/margarita-${runningMode}.properties</value>
</list>
</property>
</bean>
I would like to be able to specify my running mode in web.xml like this:
<context-param>
<param-name>runningMode</param-name>
<param-value>production</param-value>
</context-param>
So I put this bean ABOVE the 'main' property bean I described above:
<bean id="servletPropertyPlaceholderConfigurer" class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
</bean>
But that doesn't seem to work.
Is this possible with Spring? I am using version 2.5 right now.
I found this similar question:
PropertyPlaceholderConfigurer with Tomcat & ContextLoaderListener
But there is no discussion of the ServletContextPropertyPlaceholderConfigurer, so I think it is a legitimate question.
You can't do this in spring 2, without some custom coding I don't think, since one property placeholder cannot configure another.
You need to use spring 3 to get this out of the box. To accomplish this, you have to create a bean that somehow has the value you want, and use spring-el to reference that spring when setting up your property placeholder. There's a special bean for getting individual servlet context parameters as show below:
<bean id="runningMode" class="org.springframework.web.context.support.ServletContextAttributeFactoryBean">
<property name="attributeName" value="runningMode" />
</bean>
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:assuredlabor/margarita-#{runningMode}.properties</value>
</list>
</property>
</bean>
And then you can just refer to any of the properties in the normal ${} syntax
From the source code:
Subclass of PropertyPlaceholderConfigurer that resolves placeholders as ServletContext init parameters (that is, web.xml context-param entries).
Can be combined with "locations" and/or "properties" values in addition to web.xml context-params. Alternatively, can be defined without local properties, to resolve all placeholders as web.xml context-params (or JVM system properties).
If a placeholder could not be resolved against the provided local properties within the application, this configurer will fall back to ServletContext parameters. Can also be configured to let ServletContext init parameters override local properties (contextOverride=true).
Optionally supports searching for ServletContext attributes: If turned on, an otherwise unresolvable placeholder will matched against the corresponding ServletContext attribute, using its stringified value if found. This can be used to feed dynamic values into Spring's placeholder resolution.
If not running within a WebApplicationContext (or any other context that is able to satisfy the ServletContextAware callback), this class will behave like the default PropertyPlaceholderConfigurer. This allows for keeping ServletContextPropertyPlaceholderConfigurer definitions in test suites.
As I understand it, that implies that you can use just a single configurer:
<bean id="propertyPlaceholderConfigurer" class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:assuredlabor/margarita-${runningMode}.properties</value>
</list>
</property>
</bean>