I have multiple services which can return results out of thousands of classes.
Since each CXF service contains a private almost 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?
One possible way to solve it is by adding the following to the spring configuration:
<bean class="org.apache.cxf.jaxb.JAXBDataBinding" >
<constructor-arg index="0" value="#{GlobalContextBean.context}"/>
</bean>
Where the value is just a reference to a bean which holds the global (single) JAXBContext and has the following method:
public javax.xml.bind.JAXBContext getContext() {...}
You can see more details (including the CXF guru Daniel Kulp inputs) in the following thread:
Reuse-JAXB-context-in-jaxws
After testing it I've discovered that setting the current JAXBDataBinding as a global instance for multiple services won't work since there is an "if" statement in its initialize method which returns once the context was set by the first service.
That's why I've ended up by extending the class and collecting all the required services classes and model ones. After all services initialization ends, I create a global context with all required classes and return it to all services.
You can use the following class.
After all your web services are initialized call the compileGlobalJAXBContext method for creating the global context. You can add there other classes which the application needs and the init missed.
Don't Forget to configure the services to work with this bean.
public class GlobalJAXBDataBinding extends JAXBDataBinding
{
private Set<Class<?>> globalContextClasses;
private boolean contextBuilt = false;
public GlobalJAXBDataBinding(Set<Class<?>> classes) {
globalContextClasses = new HashSet<>(classes);
globalContextClasses.add(CPUUID.class);
}
public GlobalJAXBDataBinding() {
}
}
public synchronized void initialize(Service service) {
if (contextBuilt)
return;
super.initialize(service);
globalContextClasses.addAll(getContextClasses());
super.setContext(null);
}
public void compileGlobalJAXBContext() {
if (contextBuilt) return;
setContext(JAXBContext.newInstance(globalContextClasses));
contextBuilt *equals* true;
}
For some strange reason the editor didn't let me add the equal sign in the last line of compileGlobalJAXBContext so just replace the equals word with the relevant sign.