Hi
this is right and correctly done. Service are designed for CXF to get a
"prototype" scope (which is expected by default by cxf) and not a
singleton. You can get a resource in a service looking it up
(SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext().lookup("openejb:Resource/"
+ resourceId))
About $: do you want to contribute the doc? It only works between services
but is something important I think.
Another question: do you think using a Service wrapper to lookup a resource
transparently would be useful?
<Service id="myResourceAsServiceInstance"
class-name="org.apache.openejb.resource.ResourceAsService"
factory-name="get">
name = resourceId
</Service>
Implementation would be something like:
public class ResourceAsService {
private String resourceId = null; // + setter
public Object create() throws Exception {
if (id == null) {
throw new IllegalArgumentException("Please specify a resourceId");
}
return
SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext().lookup("openejb:Resource/"
+ resourceId);
}
}
Romain Manni-Bucau
Twitter: @rmannibucau
Blog: http://rmannibucau.wordpress.com/
LinkedIn: http://fr.linkedin.com/in/rmannibucau
Github: https://github.com/rmannibucau
2014-06-15 2:55 GMT+02:00 Anthony Fryer <[email protected]>:
> 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.
>