Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
339 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...