Define a custom template loader for FreeMarker with Spring - 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;

Related

Prevent Spring from meddling with CDI annotations even for factory created instances

I have a legacy product's JAR that contain Spring (4.3.8) managed classes. I need to integrate it with CDI (JavaEE 7).
I have an interface from the legacy JAR, that is implemented by a CDI bean. The CDI bean is requested from the CDI BeanManager and returned from a factory method. The factory method is registered inside Spring XML and works as expected.
The problem occurs, when a Spring bean of the legacy JAR depends on the implemented interface. Spring than injects the CDI implementation instance and scans the class it for known annotations, namingly #Inject. It then tries to resolve the dependency, which doesn't work since the dependency is not available to Spring.
I already tweaked context:property-placeholder excludes, but that changes nothing.
So how can I tell Spring to stop trying to inject something in my factory produced bean instance?
I finally was able to solve (work around) the problem. I had to remove all CDI-Annotations in the legacy JAR (by replacining them with their Spring counterparts), so spring would any longer work.
Then I added the following XML block to the applicationContext.xml of my CDI WAR:
<context:component-scan annotation-config="false" base-package="com.example">
</context:component-scan>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationTypes">
<set>
<value>org.springframework.beans.factory.annotation.Autowired</value>
<value>org.springframework.beans.factory.annotation.Value</value>
</set>
</property>
</bean>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>org.springframework.beans.factory.annotation.Qualifier</value>
</set>
</property>
</bean>
Basically that drops the support for #Inject, etc. from Spring and leaves it where it belongs: CDI.
It's a bit easier.
AutowiredAnnotationBeanPostProcessor is already a bean, so you can configure it before Spring starts to scan with a ServletContextListener to exclude #Inject annotations. At least from Spring 4.1+, AutowiredAnnotationBeanPostProcessor has a method setAutowiredAnnotationTypes, e.g.:
#WebListener
public class ApplicationConfigListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
ApplicationContext appCtx = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>();
AutowiredAnnotationBeanPostProcessor bean = appCtx.getBean(AutowiredAnnotationBeanPostProcessor.class);
autowiredAnnotationTypes.add(Autowired.class);
autowiredAnnotationTypes.add(Value.class);
bean.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
}
}
You could use a SpringBeanAutowiringInterceptor too.
This is explained here.

How would I make this bean in JavaConfig, I dont want to use XML with Spring anymore

I am working on a project and I need to set the following bean and property but I dont want to do it in XML.. I want to do it in JavaCofig style.. Can someone please show me how I would do this in javaconfig stlye
<!-- Spring Configuration needed to avoid URI using dots to be truncated -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false" />
</bean>
Something like this should work:
#Bean public DefaultAnnotationHandlerMapping defaultAnnotationHandlerMapping(){
DefaultAnnotationHandlerMapping bean = new DefaultAnnotationHandlerMapping();
bean.setUseDefaultSuffixPattern(false);
return bean;
}
You can see my sample spring MVC app using code config here https://github.com/robhinds/spring-code-configuration-webapp/blob/master/src/main/java/com/tmm/web/configuration/WebMvcConfiguration.java

Spring loading properties from a bean

I am currently usinmg PropertyPlaceholderConfigurer to load properties into my spring context, however I want to have a custom hierarchy/overriding of property files that I am handling in a Java class. Can I have my class, which itself is a bean in the context, inject the properties into the context?
e.g.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:/config/conf.properties" />
</bean>
<bean id="config" class="com.main.Config" />
My Config class has a Properties getProperties() method -- can I wire that into spring somehow? Obviously the properties would not be loaded until the config bean is created or inited.
Thanks!
Update: As suggested by the answer I change my Config to Config extends PropertySource<Properties> and had to write a small wrapper around MutablePropertySources that takes a single PropertySource and then my xml looks like this:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="propertySources">
<bean class="com.main.ConfigMutablePropertySources">
<constructor-arg name="propertySource" ref="config" />
</bean>
</property>
</bean>
Where:
public class ConfigMutablePropertySources extends MutablePropertySources {
public ConfigMutablePropertySources(PropertySource<?> propertySource) {
super(new MutablePropertySources());
addLast(propertySource);
}
}
Looking at the methods available (from JavaDoc for PropertyPlaceholderConfigurer) suggests to me no easy way to do such a thing.
The general comment at the top suggests that, as of Spring 3.1, one should prefer to use PropertySourcesPlaceholderConfigurer instead. Using this solution, it appears that you could register your own set of PropertySource objects via the setPropertySources(...) method. Of course your Config class would have to be fit into the interface (abstract class actually) of PropertySource.
It is worth noting that using the setPropertySources(...) method above will assume nothing else about your property sources and will therefore not add the default property sources (Environment and Local properties).

Using Jaxb2Marshaller to unmarshall an xml and validate against a schema

I am implementing a REST service with xml as the payload and have the following configuration to use Jaxb2Marshaller to unmarshall my xml. Here is the configuration from my spring context file
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.my.examples.Product</value>
</list>
</property>
<property name="schema" value="classpath:schemadefinitions/product.xsd" />
</bean>
On my bean Product I have just this annotation as
#XmlRootElement(name="product")
public class ProductInfo {
The issue is when I make the REST request it unmarshalls xml to bean properly but doesn't perform any validation against the schema configured with the marshaller. Am I missing anything ?
I had to attach a validationeventhandler to the marshaller as jaxb2Mashaller.setValidationEventHandler(...) Once this is set the unmarshaller started to validate input xml.
With Java 8 and JaxB 2.2.4, I don't see any problems with the original setup! Defining the schema property in the applicationcontext.xml is ALL you need to do in order to get schema validation going.
If one creates Jaxb2Marshaller "manually", one needs to make sure to call the afterPropertiesSet method after setting the schema resource, since it loads the schema resource into memory.

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