Hello Avner,

I did this once because of the same idea. In the end I decided to remove this 
because this caused too much trouble due 
to the nature of the implementation of the JAXBContext. Anyways, this is the 
way I did that:

First of all, you need a good way to initialize the JAXBContext. I was using 
Freemaker for this.

/src/main/freemarker/jaxb-packages.fmt:

        <@file package="package.of.jaxb.generated.classes" name="jaxb.packages">
        <@forAllPackages var="package">
        <#assign printpackage=false>
        <#list package.classes as class>
        <@ifHasAnnotation declaration=class 
annotation="javax.xml.bind.annotation.XmlRegistry">
        <#assign printpackage=true>
        </@ifHasAnnotation>
        </#list>
        <#if printpackage>
        ${package.qualifiedName}
        </#if>
        </@forAllPackages>
        </@file>

Run this code using the apt-maven-plugin after the maven-jaxb2-plugin:

       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>apt-maven-plugin</artifactId>
         <configuration>
           
<factory>net.sf.jelly.apt.freemarker.FreemarkerProcessorFactory</factory>
           <fork>false</fork>
           <options>
             
<value>template=${basedir}/src/main/freemarker/jaxb-packages.fmt</value>
           </options>
           <outputDirectory>${project.build.outputDirectory}</outputDirectory>
           
<sourceOutputDirectory>${project.build.outputDirectory}</sourceOutputDirectory>
           <additionalSourceRoots>
             
<additionalSourceRoot>target/generated-sources/java</additionalSourceRoot>
           </additionalSourceRoots>
         </configuration>
         <executions>
           <execution>
             <goals>
               <goal>process</goal>
             </goals>
           </execution>
         </executions>
         <dependencies>
           <dependency>
             <groupId>net.sf.apt-jelly</groupId>
             <artifactId>apt-jelly-core</artifactId>
             <version>2.14</version>
           </dependency>
           <dependency>
             <groupId>net.sf.apt-jelly</groupId>
             <artifactId>apt-jelly-freemarker</artifactId>
             <version>2.14</version>
           </dependency>
         </dependencies>
       </plugin>

This will generate a file which contains all the packages of the generated JAXB 
classes. One package per line. You will 
need these packages to initialize the JAXBContext for all your classes at once.

Now, I have added a JAXBContextProvider. (Note: there are OVal annotations in 
this code)

        /**
         * @author Marko Voss ([email protected])
         */
        @Guarded
        @Provider
        public class JAXBContextProvider {
        
            private static final Logger LOG = 
LoggerFactory.getLogger(JAXBContextProvider.class);
        
            private JAXBContext jaxbContext;
        
            private String packageFile;
        
            protected JAXBContextProvider() {}
        
            @NotNull
            public final JAXBContext getJAXBContext() throws JAXBException {
                if (this.jaxbContext == null) {
                    this.jaxbContext = initJAXBContext();
                    if (this.jaxbContext == null) {
                        this.jaxbContext = JAXBContext.newInstance();
                        LOG.warn("Returning default JAXBContext instance.");
                    }
                }
                return this.jaxbContext;
            }

            public final void setPackageFile(@NotNull @NotBlank final String 
packageFile) {
                this.packageFile = packageFile;
            }

            private JAXBContext initJAXBContext() throws JAXBException {
                if (this.packageFile == null) return null;
        
                final InputStream stream = 
getClass().getClassLoader().getResourceAsStream(this.packageFile);
                try {
                    if (stream != null) {
                        final BufferedReader reader = new BufferedReader(new 
InputStreamReader(stream));
                        final StringBuilder packages = new StringBuilder();
        
                        String line;
                        while ((line = reader.readLine()) != null) {
                            packages.append(line);
                            packages.append(':');
                        }
                        packages.deleteCharAt(packages.length() - 1);
                        return JAXBContext.newInstance(packages.toString());
                    } else {
                        LOG.warn("Unable to find JAXB package list: " + 
this.packageFile);
                    }
                } catch (IOException e) {
                    LOG.error("Error reading JAXB package list: " + 
this.packageFile, e);
                }
                return null;
            }
        }

Now, register the JAXBContextProvider to the JAXBElementProvider:

        public class MyJAXBElementProvider extends JAXBElementProvider<Object> {

          private JAXBContextProvider jaxbContextProvider;

          // register
          public void setJaxbContextProvider(final JAXBContextProvider 
jaxbContextProvider) {
            this.jaxbContextProvider = jaxbContextProvider;
          }

          public JAXBContext getJAXBContext(Class<?> type, Type genericType) 
throws JAXBException {
             if (this.jaxbContextProvider != null) {
               return this.jaxbContextProvider.getJAXBContext();
             } else {
               return super.getJAXBContext(type, genericType);
             }
          }
        }

I configured this using Spring.

The JAXBContext will now be available for all the generated JAXB classes. BUT 
this works only for unmarshalling! (iirc) 
On marshalling I got the problem, that the JAXBContext was not able to 
recognize some namespaces or something. I cannot 
really remember the problem. In the end I have decided to remove this, because 
it is just not possible to have one 
context for everything. I think the problem was like this:

The XML allows any content and you put some XML inside this any content. You 
have JAXB objects for both XML structures, 
the outside one and the "any-content one". Iirc, the JAXBContext was not able 
to map the inner XML to an object because 
of it could not find the JAXB object mapping for it, even through it was 
registered. Due to lack of time I did not 
investigate this any further.


best

Am 02.10.2012 14:16, schrieb Avner Levy:
> Hi,
> I have multiple services which can return results out of thousands of classes.
> Since each CXF service contains a private otherwise-identical JAXB context, 
> it causes a huge memory waste.
> Is there a way to create the JAXB context myself and share it between the 
> services?
> Thanks in advance,
>   Avner


-------------------------------------------------------

Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische 
Information mbH. 
Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 
101892. 
Geschäftsführerin: Sabine Brünger-Weilandt. 
Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.


Reply via email to