I've managed (after lots of pain and suffering) to get my web services using the same JAXBContext. The great thing is this significantly speeds up my tomee boot time. Before, tomee was taking 37594 ms to boot and now it is taking 10150 ms, so the performance gain is massive. The steps i went through to get this to work are detailed below.
I tried to follow the steps described in https://www.mail-archive.com/[email protected]/msg35563.html, changing the spring config into tomee config. So the idea was to try to create a global JAXBContext instance and then pass that as a constructor parameter into the org.apache.cxf.jaxb.JAXBDataBinding. I thought I could do this using <Service> elements in my resources.xml file. I created a class to create the JAXBContext... public class GlobalJAXBContext { public static JAXBContext getJAXBContext() { try { return JAXBContext.newInstance(new Class[] { com.virginaustralia.model.schema.utility.ObjectFactory.class, com.virginaustralia.service.contract.departure_management.ObjectFactory.class }); } catch (JAXBException e) { e.printStackTrace(); } return null; } } Then I added the following to my resources.xml... <resources> ... <Service id="myJAXBContext" class-name="com.virginaustralia.service.GlobalJAXBContext " factory-name="getJAXBContext"/> <Service id="myJAXBDataBinding" class-name="org.apache.cxf.jaxb.JAXBDataBinding" constructor="jaxbContext"> jaxbContext = $myJAXBContext </Service> </resources> Took me a long time and looking through source code to discover you can pass other services as a constructor parameter using the $<serviceId> notation. My openejb-jar.xml then looked like this... <openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1"> <ejb-deployment ejb-name="AcceptPaymentForAncillariesImpl"> <properties> cxf.jaxws.databinding = myJAXBDataBinding </properties> </ejb-deployment> <ejb-deployment ejb-name="ActivatePassengerBagTagImpl"> <properties> cxf.jaxws.databinding = myJAXBDataBinding </properties> </ejb-deployment> ... plus 30 other services similar to above </openejb-jar> Booting tomee after this change is where the errors started happening. First error was this one... org.apache.cxf.service.factory.ServiceConstructionException: Service class com.virginaustralia.service.contract.departure_management.DeletePassengerBagTagPortType method deletePassengerBagTag part {urn:www.virginaustralia.com:service:contract:departure-management}request cannot be mapped to schema. Check for use of a JAX-WS-specific type without the JAX-WS service factory bean. To fix this, i had to specify the wsdlLocation in the @WebService annotation. Fortunately you can do this using a classpath url (this requires you to package the WSDL with the service and port classes generated using wsimport). @Stateless @Local(AcceptPaymentForAncillariesPortType.class) @WebService( portName="AcceptPaymentForAncillariesPortType", serviceName="AcceptPaymentForAncillariesService", targetNamespace = "urn:www.virginaustralia.com:service:contract:departure-management", endpointInterface="com.virginaustralia.service.contract.departure_management.AcceptPaymentForAncillariesPortType", wsdlLocation="classpath:/com/virginaustralia/service/contract/departure_management/AcceptPaymentForAncillaries.wsdl" ) public class AcceptPaymentForAncillariesImpl implements AcceptPaymentForAncillariesPortType { ... } After adding wsdlLocation to every service, I booted tomee, but the boot time was exactly the same. Turns out that a new instance of the "myJAXBDataBinding" service defined in resources.xml was being instantiated for every web service. And since i used the "myJAXBContext" as a constructor argument, a new JAXBContext was being created for every service and consequently i was no better off than before. I only wanted a single JAXBContext created, so I tried to configure it as a Resource instead of a Service as below... <resources> ... <Resource id="myJAXBContext" class-name="com.virginaustralia.service.GlobalJAXBContext " factory-name="getJAXBContext"/> <Service id="myJAXBDataBinding" class-name="org.apache.cxf.jaxb.JAXBDataBinding" constructor="jaxbContext"> jaxbContext = $myJAXBContext </Service> </resources> Unfortunately when i tried that, the $myJAXBContext being passed as a constructor parameter was null. Is there a way you can pass a resource to a service as a constructor parameter? To get around this, I had to change the Resource back to being a Service and modify my class that creates the JAXBContext to only return a singleton instance... public class GlobalJAXBContext { private static JAXBContext jaxbContext = null; public static JAXBContext getJAXBContext() { if (jaxbContext == null) { try { jaxbContext = JAXBContext.newInstance(new Class[] { com.virginaustralia.model.schema.utility.ObjectFactory.class, com.virginaustralia.service.contract.departure_management.ObjectFactory.class }); } catch (JAXBException e) { e.printStackTrace(); } } return jaxbContext; } } After that change, all my services were booting up successfully and reusing a single JAXBContext. Regards, Anthony -- View this message in context: http://openejb.979440.n4.nabble.com/Use-single-JAXBContext-for-multiple-web-services-tp4670019p4670021.html Sent from the OpenEJB User mailing list archive at Nabble.com.
