Add a list of groovy files using <lang:groovy> - spring

I have integrated groovy in my application using spring. My context looks like:
<lang:groovy id="myConfiguration"
script-source="classpath:MyGroovy.groovy"
refresh-check-delay="1000"/>
MyGroovy is an implementation of MyInterface. I was wondering how can I add more files in my classpath (also implementing the same interface) and to have more beans like the one above dynamically?
I would like to get something like:
<lang:groovy id="myConfiguration"
script-source="classpath:*.groovy"
refresh-check-delay="1000"/>
And later be able to use a list of implementations of MyInterface and sent it to another bean where I can go through the list and do stuff. My bean would like like:
<bean id="myProcessor"
class="com.package.processor.MyProcessor">
<constructor-arg>
<list value-type="com.package.processor.MyInterface">
<bean class="MyGroovy1"/>
<bean class="MyGroovy2"/>
<bean class="MyGroovy3"/>
</list>
</constructor-arg>
</bean>
Is this possible at all? I have just changed the first part and I already get Exceptions and haven't found in the documentation anything related to this topic.
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'myProcessor': Could not determine
scripted object type for GroovyScriptFactory: script source locator
[classpath:.groovy]; nested exception is
java.io.FileNotFoundException: class path resource [.groovy] cannot
be opened because it does not exist

Related

Loading Bean without explicitly referencing or retrieving it

In my application I use an XML Application Context to configure and build Spring beans.
I have a bean which is an observer and an observed bean. The configuration looks something like
<bean class="com.example.Observer">
<property name="observedBean">
<bean class="com.example.Observed" />
</property>
</bean>
My problem is, that there is nobody explicitly asking for a reference of the observer neither the observer nor the observed bean will be created.
Since there is no need of an explicit reference I would like to avoid just asking the ApplicationContext for a reference to just ignore it again.
Is there any solution for my problem or do I have a problem with my concept?

Define a custom template loader for FreeMarker with Spring

I'm trying to use FreeMarker to create html for sending an email using Spring. I do not want to access the templates from files, but rather get it from db (Mongo, but any db would be the same).
My current configuration is as follows:
<!-- freemarker config -->
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="preTemplateLoaders">
<list>
<ref bean="databaseTemplateLoader"/>
</list>
</property>
</bean>
<bean name="databaseTemplateLoader" class="com.myapp.service.MongoDBToFreeMarkerTemplateLoader"/>
When I autowire the Configuration object I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [freemarker.template.Configuration] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
I use the following code to Autowire:
#Autowired
Configuration freeMarkerTemplateEngine;
Without dependency injection (i.e. when using "new Configuration()" and manually setting the custom loader), it works fine, but obviously I want to stick to DI here.
Is there anything else I need to define in order to do this? I've followed this blog and it didn't say anything else is needed.
Well, I figured it out.
As it turns out, there were two problems here:
I put the factory bean configuration in spring-servlet.xml, next to
the freemarkerViewResolver which probably made it available to the
view resolver, but invisible to the rest of the application. Moving
this config to applicationcontext.xml was step one in solving this
problem.
I had a Maven misconfiguration. When I added FreeMarker to
my POM.XML file, I did not set the scope. The default scope is
Compilation, which means that Configuration class was not available
at runtime. Adding runtime to the freemarker maven
include fixed that one.
It now works!
To be able to use Spring's tag lib with a custom template loader
<#import "spring.ftl" as spring />
you need to do the following (using Java configuration):
public FreeMarkerConfigurer getFreemarkerConfig(DBTemplateLoader dbTemplateLoader) throws IOException, TemplateException {
FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean = new FreeMarkerConfigurationFactoryBean();
freeMarkerConfigurationFactoryBean.setPreTemplateLoaders(new ClassTemplateLoader(FreeMarkerConfigurer.class, ""), dbTemplateLoader);
FreeMarkerConfigurer result = new FreeMarkerConfigurer();
result.setConfiguration(freeMarkerConfigurationFactoryBean.createConfiguration());
return result;
}
I believe this is because Spring cannot find the matching bean defined in your applicationContext.
Since you define freemarker configuration bean like this:
<!-- freemarker config -->
<bean id="freemarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="preTemplateLoaders">
<list>
<ref bean="databaseTemplateLoader"/>
</list>
</property>
</bean>
<bean name="databaseTemplateLoader" class="com.myapp.service.MongoDBToFreeMarkerTemplateLoader"/>
Then in your code, you should inject bean with the name freemarkerConfiguration as below:
#Autowired
FreeMarkerConfigurationFactoryBean freemarkerConfiguration;

Trouble integrating a library using Apache Commons Config with Spring project using PropertyPlaceholderConfigurer

I have a custom library that sends a JMS notification. The idea is that you can use the library by simply by setting some properties in your project.
The custom library is using the Apache Commons Configuration. (The reason I mention this is that I suspect it may be playing a role in my problem). I'm trying to use it in my current Spring project which doesn't use Commons Config but uses the PropertyPlaceholderConfigurer. I've got the properties I need written out in a .properties file.
I've added the library as a dependency in my pom.xml file. I tried adding it into my web.xml like so
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
...
classpath:mylibrary-context.xml
</param-value>
</context-param>
When creating a bean in my Spring project, I tried to reference one of the beans defined in the library, so I could use it. There's an error creating one of the library beans that requires a property from my properties file.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'libraryBean' defined in class path resource [mylibrary-context.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'boolean' for property 'useCompression'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [${foo.bar.use.compression}]
I know some of the other properties files in the project have boolean properties set the exact same way without issue. Here is how I'm loading the properties files in the applicationContext.xml(which after checking the logs, seems to load correctly)
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
...
<!-- loaded in order-->
<value>classpath:foo/bar/some-props.properties</value>
<value>classpath:foo/bar/some-monitoring.properties</value>
<value>file:/${user.home}/foo/bar/some-monitoring.properties</value>
<value>file:/etc/foo/bar/some-monitoring.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
and finally my some-monitoring.properties file:
foo.bar.use.compression=true
foo.bar.name=foobar
foo.bar.broker.url=someurl
So I'm just wondering what's going on with the boolean property and why? If its a general problem with the PropertyPlaceholderConfigurer not loading boolean properties, its odd that I'm not having a problem with the other properties files. Is it that there is some conflict because of the library using the Commons Configuration? My knowledge of how Spring loads up these properties is pretty shallow so this seems like a chance to get a better handle on what's going on under the covers.
If anyone can shed some light on what's going on and how to fix/get around it, any help is greatly appreciated!
Quoting Jurgen on the spring-dev list:
PropertyPlaceholderConfigurer is an implementation of the BeanFactoryPostProcessor interface: This interface and its sibling
BeanPostProcessor just apply to the BeanFactory that defines them,
that is, to the application context that defines them.
If you combine multiple config files into a single
contextConfigLocation, a PropertyPlaceholderConfigurer defined in any
of the files will apply to all of the files, because they are loaded
into a single application context.
As far as I understand, you tried to combine all your application contexts into the contextConfigLocation. According to the quotation, it should work fine. I think that you have other kind of problem. In my opinion both boolean and string properties are not loaded at all. Maybe it seems as string properties are loaded, but I think that their values are set to ${foo.bar.name} and ${foo.bar.broker.url}. Since they are Strings, they can hold these values. When Spring tries to set ${foo.bar.use.compression} to the boolean, you have typecast problem which just reveals wider issue.
Probably, if you set:
<property name="ignoreResourceNotFound" value="false"/>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
you will see that PropertyPlaceHolderConfigurer cannot resolve your properties files.
Please also try using classpath*: notation when you refer to resources from other JARs.

bean class instantiation in spring for a class without default constructor

I am using a third party library class XYZ as an argument in my model. XYZ does not have a default constructor. So spring is not able to create bean for it giving error message as
org.springframework.web.util.NestedServletException: Request processing failed;
nested exception is org.springframework.data.mapping.model.MappingInstantiationException:
Could not instantiate bean class [org.abc.def.XYZ]: No default constructor found;nested exception is java.lang.NoSuchMethodException: org.abc.def.XYZ./<init/>()
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:681)
What can I do to resolve this ? I can't add default constructor to XYZ.
I added the following in my dispatcher servlet, but it still don't works.
<bean name="token" class="org.abs.def.Xyx">
<constructor-arg name="arg1" value="val1"/>
<constructor-arg name="arg2" value="val2"/>
<constructor-arg name="arg3" value="val3"/>
</bean>
Thanks.
You can define it in the XML file as a spring bean passing all necessary parameters to instantiate it.
sample:
<bean id="xyz" class="com.a.b.Xyz" >
<constructor-arg index="0" ref="anotherBean"/>
<constructor-arg index="1" value="12"/>
</bean>
You'll need to provide <constructor-arg> elements in your application context config file, as described in the documentation.

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.

Resources