Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
359 views
in Technique[技术] by (71.8m points)

java - Reuse CXF jaxb context between multiple services

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

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

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...