Add the ability to Scan Packages for JAXB Marshalling (java example provided) [SPR-8986] #13626
In our application we have a rapidly growing number of JAXB2 annotated classes. It is a right pain to add these classes manually to the "classesToBeBound" property in the Jaxb2Marshaller. Given that other components (I'm looking at you Hibernate : AnnotationSessionFactoryBean) have the ability to automatically add classes from packages that match annotations, why not then for the Jaxb2Marshaller (having to key in the classes manually is so old skool).
I've extended Jaxb2Marshaller (file attached) that scans on the classpath for appropriately annotated classes. Please do review and I hope that this can be incorporated into the next release. I'm happy to make changes to the codebase if required to bring it up to Spring coding standards.
It's a pity that afterPropertiesSet is marked as Final in Jaxb2Marshaller since I can't override that method to set up the setClassesToBeBound before then calling the super afterPropertiesSet. Currently as the code stands, I have to provide a dummy setClassesToBeBound and setLazyInit to be true. This dummy is then replaced by overriding the getJaxbContext. I think this needs rewriting.
An example of use:
<bean id="marshaller" class="foo.bar.AnnotationJaxb2Marshaller"> <property name="lazyInit" value="true" /> <property name="classesToBeBound"> <list> <value>foo.bar.Class</value> </list> </property> <property name="packagesToScan"> <list> <value>foo.bar.jaxb.model</value> </list> </property> </bean>
Affects: 3.1 GA
The text was updated successfully, but these errors were encountered:
Arjen Poutsma commented
What's the advantage of this feature compared to the contextPath property that's already there? For instance, the example you give could also be:
<bean id="marshaller" class="foo.bar.AnnotationJaxb2Marshaller"> <property name="contextPath" value="foo.bar.jaxb.model" /> </bean>
or you could use the contextPaths property if you have multiple packages.
David Harrigan commented
Oops, sorry for the formatting, forgot the appropriate keywords:
Thanks for your comments Arjen, here are my replies:
Setting the ContextPath ultimately calls newInstance on JAXBContext. According to the JAXB documentation
each package has to be explicitly set by the programmer. The advantage of my approach is that I use the same approach as the AnnotationSessionFactoryBean used in the ORM package to automatically scan all packages and sub packages to help the programmer out. I can simply set a top level package and let Spring do the work for me instead of me listing every package and sub package manually.
Again, according to the JAXBContext documentation, even if I do set the packages using the contextPath, it must follow these constraints:
Naturally, I don't want to create a jaxb.index file in each package since using Annotations should be sufficient. Reading the javadoc, it appears that if I fail to meet ONE or BOTH of the conditions, then a JAXBException will be thrown. The beauty of my approach is that you don't need to do that, I collate together a list of annotated classes and call the newInstance method on JAXBContext that uses an Array of Classes - just like the classesToBeBound method does.
Thank you Arjen, look forward to you reply
David Harrigan commented
How's it going? Do you think my reply to be reasonable in that by providing package scanning for JAXB annotated classes to be another valid approach to building the JAXBContext?
I recongise that there would be work for the XSD to do - but I'm not great at that :-)