Spring Framework
  1. Spring Framework
  2. SPR-8986

Add the ability to Scan Packages for JAXB Marshalling (java example provided)

    Details

    • Last commented by a User:
      false

      Description

      Hi,

      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>
      

      =david=

      1. AnnotationJaxb2Marshaller_v2.java
        5 kB
        David Harrigan
      2. AnnotationJaxb2Marshaller.java
        4 kB
        David Harrigan

        Issue Links

          Activity

          Hide
          David Harrigan added a comment -

          Oops, sorry, lazyInit is not required. I misread the code However, the classesToBeBound is required still. Just a dummy value to get round the check.

          Show
          David Harrigan added a comment - Oops, sorry, lazyInit is not required. I misread the code However, the classesToBeBound is required still. Just a dummy value to get round the check.
          Hide
          David Harrigan added a comment -

          Hi,

          A fix for the getJaxbContext - this time, just ignore the classesToBeBound if packagesToScan is not empty.

          Also make a defensive copy of the packagesToScan (good programming practice.)

          =david=

          Show
          David Harrigan added a comment - Hi, A fix for the getJaxbContext - this time, just ignore the classesToBeBound if packagesToScan is not empty. Also make a defensive copy of the packagesToScan (good programming practice.) =david=
          Hide
          David Harrigan added a comment -

          Hi,

          I've created a pull request on GitHub with proposed code changes to the Jaxb2Marshaller to enable package scanning.

          https://github.com/SpringSource/spring-framework/pull/15

          =david=

          Show
          David Harrigan added a comment - Hi, I've created a pull request on GitHub with proposed code changes to the Jaxb2Marshaller to enable package scanning. https://github.com/SpringSource/spring-framework/pull/15 =david=
          Hide
          Arjen Poutsma added a comment -

          Hey,

          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 contextPath*s* property if you have multiple packages.

          Show
          Arjen Poutsma added a comment - Hey, 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 contextPath*s* property if you have multiple packages.
          Hide
          David Harrigan added a comment -

          Oops, sorry for the formatting, forgot the appropriate keywords:

          Hi,

          Thanks for your comments Arjen, here are my replies:

          1.
          Setting the ContextPath ultimately calls newInstance on JAXBContext. According to the JAXB documentation

          JAXBContext from Java6 JavaDoc

          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.

          2.
          Again, according to the JAXBContext documentation, even if I do set the packages using the contextPath, it must follow these constraints:

          Every package listed on the contextPath must meet one or both of the following conditions otherwise a JAXBException will be thrown:
          it must contain ObjectFactory.class
          it must contain jaxb.index

          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=

          Show
          David Harrigan added a comment - Oops, sorry for the formatting, forgot the appropriate keywords: Hi, Thanks for your comments Arjen, here are my replies: 1. Setting the ContextPath ultimately calls newInstance on JAXBContext. According to the JAXB documentation JAXBContext from Java6 JavaDoc 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. 2. Again, according to the JAXBContext documentation, even if I do set the packages using the contextPath, it must follow these constraints: Every package listed on the contextPath must meet one or both of the following conditions otherwise a JAXBException will be thrown: it must contain ObjectFactory.class it must contain jaxb.index 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=
          Hide
          David Harrigan added a comment -

          Hi Arjen,

          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

          =david=

          Show
          David Harrigan added a comment - Hi Arjen, 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 =david=
          Hide
          Arjen Poutsma added a comment -

          Hey David,

          I'm currently working on it...

          Show
          Arjen Poutsma added a comment - Hey David, I'm currently working on it...
          Hide
          David Harrigan added a comment -

          Hi Arjen,

          That is great news If I can be of any help at all, please do ask

          =david=

          Show
          David Harrigan added a comment - Hi Arjen, That is great news If I can be of any help at all, please do ask =david=
          Hide
          Arjen Poutsma added a comment -

          Fixed.

          Show
          Arjen Poutsma added a comment - Fixed.

            People

            • Assignee:
              Arjen Poutsma
              Reporter:
              David Harrigan
              Last updater:
              Trevor Marshall
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                2 years, 13 weeks ago