tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Romain Manni-Bucau <rmannibu...@gmail.com>
Subject Re: Use single JAXBContext for multiple web services
Date Sun, 15 Jun 2014 10:18:28 GMT
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 <apfryer@hotmail.com>:

> 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/users@cxf.apache.org/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.
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message