Using Jaxb2Marshaller to unmarshall an xml and validate against a schema - spring

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.

Related

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;

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).

Setting property reference for a bean programmatically

Right now i am using the following bean entry
<bean id="Service" >
<property name="target">
<bean class="someClass" lazy-init="false">
<property name="SessionFactory1"><ref bean="SessionFactory1"/></property>
<property name="SessionFactory2"><ref bean="SessionFactory2"/></property>
<property name="SessionFactory3"><ref bean="SessionFactory3"/></property>
</bean>
</property>
</bean>
Now the requirement is to first check which all session factories have an active datasource and include those only in the above bean definition. So that the application does not break if we try to initialize a session factory with inactive datasource.
sessionfactory initialization will be take care by using seperate config xml for session factories and loading only the ones with active datasources.
Please help on how can this be achieved.
You can use Spring InitializingBean interface, which makes you implement an afterPropertiesSet() method. This method will be executed after Spring instantiates your class, and you could check if your session factories are available or not.
InitializingBean: Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: for example, to perform custom initialization, or merely to check that all mandatory properties have been set.
link: Spring InitializingBean

how can I specify schema validate in Spring 3 config file with <oxm:jaxb2-marshaller> element?

I choose to use Spring Jaxb2Marshaller to support JAXB in my project, but I cannot specify a schema file in element oxm:jaxb2-marshaller, I found only a contextPath property, nothing about schema.
Must I use the old Jaxb2Marshaller config style (using beans:bean element)?
The class Jaxb2Marshaller has a schema property, try this sample of code.
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>my.package.ResponseObj</value>
</list>
</property>
<!-- Possibly include schema for validation -->
<property name="schema" value="classpath:schema.xsd"/>
</bean>
EDIT :
I think that you can't specify an XML schema directly in the config file with the new OXM balise. There is no xml element or attribut for this in the OXM XSD. But you can use the new #XmlSchema annotation directly in your "classe to bound". Look this documentation.

Resources